<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link href="common/css/sf.css" rel="stylesheet" type="text/css"/>
<title>MoreStlc: 扩展简单类型 Lambda-演算</title>
</head>
<link href="common/jquery-ui/jquery-ui.css" rel="stylesheet">
<script src="common/jquery-ui/external/jquery/jquery.js"></script>
<script src="common/jquery-ui/jquery-ui.js"></script>
<script src="common/toggleproofs.js"></script>
<link href="common/css/plf.css" rel="stylesheet" type="text/css"/>

<body>

<div id="page">

<div id="header">
<a href='https://coq-zh.github.io/SF-zh/index.html'>
<img src='common/media/image/sf_logo_sm.png'></a>
</br><a href='index.html'>  <span class='booktitleinheader'>Volume 2: 编程语言基础</span><br></br>
<ul id='menu'>
   <a href='toc.html'><li class='section_name'>目录</li></a>
   <a href='coqindex.html'><li class='section_name'>索引</li></a>
   <a href='deps.html'><li class='section_name'>路线</li></a>
</ul>
</a></div>

<div id="main">

<h1 class="libtitle">MoreStlc<span class="subtitle">扩展简单类型 Lambda-演算</span></h1>


<div class="code code-tight">

<span class="id" type="keyword">Set</span> <span class="id" type="var">Warnings</span> "-notation-overridden,-parsing".<br/>
<span class="id" type="var">From</span> <span class="id" type="var">PLF</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Maps</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">PLF</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="keyword">Types</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">PLF</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Smallstep</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">PLF</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Stlc</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">Coq</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Strings.String</span>.<br/>
</div>

<div class="doc">
<a name="lab246"></a><h1 class="section">STLC 的简单扩展</h1>

<div class="paragraph"> </div>

 简单类型 lambda-演算在理论上有一些有趣的性质，但由于缺乏一些结构使其还不足以成为一个实用的编程语言。

<div class="paragraph"> </div>

    在本章中，我们引入一些常见的特性来缩小和现实世界中程序语言的距离，这些新的特性
    在类型层面上是简单和直接的。
<div class="paragraph"> </div>

<a name="lab247"></a><h2 class="section">数值</h2>

<div class="paragraph"> </div>

 在 <span class="inlinecode"><span class="id" type="var">StlcProp</span></span> 一章最后的 <span class="inlinecode"><span class="id" type="var">stlc_arith</span></span> 练习中，我们看到为 STLC
    添加自然数、常量和原始操作（primitive operation）十分容易的——
    基本只需要将我们在 <a href="Types.html"><span class="inlineref">Types</span></a> 和 <a href="Stlc.html"><span class="inlineref">Stlc</span></a> 中学到的内容结合起来。
    添加机器整数或浮点数这些类型同样直接，当然语言中数值的规格也会更加精确。
<div class="paragraph"> </div>

<a name="lab248"></a><h2 class="section">Let 绑定</h2>

<div class="paragraph"> </div>

 当写一个复杂的表达式时，为一些子表达式命名常常可以避免重复计算和提高可读性。
    多数语言都提供了多种这样的机制。比如，在 OCaml（以及 Coq）中，我们可以写 <span class="inlinecode"><span class="id" type="keyword">let</span></span>
    <span class="inlinecode"><span class="id" type="var">x</span>=<span class="id" type="var">t<sub>1</sub></span></span> <span class="inlinecode"><span class="id" type="keyword">in</span></span> <span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span>，意思是说“首先归约 <span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> 到一个值，并绑定到 <span class="inlinecode"><span class="id" type="var">x</span></span> 上，同时继续对 <span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span>
    归约。”

<div class="paragraph"> </div>

    我们的 <span class="inlinecode"><span class="id" type="keyword">let</span></span> 绑定使用的求值策略和 OCaml 相同，均为标准的<b>传值调用（call-by-value）</b>，
    也即在对 <span class="inlinecode"><span class="id" type="keyword">let</span></span> 的主体（即 <span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span>）归约前，被绑定的项（即 <span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span>）必须已经完全归约。
    类型规则 <span class="inlinecode"><span class="id" type="var">T_Let</span></span> 告诉我们可以这样为 <span class="inlinecode"><span class="id" type="keyword">let</span></span> 表达式定型：首先计算被绑定项的类型，
    用此类型和对应的绑定名扩展上下文，并在新的上下文中对 <span class="inlinecode"><span class="id" type="keyword">let</span></span> 主体定型
    （最后得到的类型便是整个 <span class="inlinecode"><span class="id" type="keyword">let</span></span> 表达式的类型）。

<div class="paragraph"> </div>

    类型规则和自然语言的文本描述了同样的内容，但读者基于在本书中已经学过的内容，
    理解前者应当已经比较容易了。如下： 
<div class="paragraph"> </div>

 语法：
<pre>
       t <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                项
           | ...               （与之前的其他项相同）
           | let x=t in t      let-绑定
</pre>

<div class="paragraph"> </div>


<div class="paragraph"> </div>

    归约规则：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">t<sub>1</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>1</sub>'</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_Let1) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">let&nbsp;x=t<sub>1</sub>&nbsp;in&nbsp;t<sub>2</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;let&nbsp;x=t<sub>1</sub>'&nbsp;in&nbsp;t<sub>2</sub></td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_LetValue) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">let&nbsp;x=v<sub>1</sub>&nbsp;in&nbsp;t<sub>2</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;[x:=v<sub>1</sub>]t<sub>2</sub></td>
  <td></td>
</td>
</table></center>    定型规则：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t<sub>1</sub>&nbsp;&#x2208;&nbsp;T<sub>1</sub>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x<span class="nowrap"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span></span>T<sub>1</sub>;&nbsp;Gamma&nbsp;&#x22A2;&nbsp;t<sub>2</sub>&nbsp;&#x2208;&nbsp;T<sub>2</sub></td>
  <td class="infrulenamecol" rowspan="3">
    (T_Let) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;let&nbsp;x=t<sub>1</sub>&nbsp;in&nbsp;t<sub>2</sub>&nbsp;&#x2208;&nbsp;T<sub>2</sub></td>
  <td></td>
</td>
</table></center>
<div class="paragraph"> </div>

<a name="lab249"></a><h2 class="section">二元组</h2>

<div class="paragraph"> </div>

 Coq 中的函数式编程经常使用一<b>对（pair）</b>值，而其类型为<b>积类型（product type）</b>。

<div class="paragraph"> </div>

    对二元组（序对）的形式化非常简单，以至于不需要太多讨论。然而，还是让我们看看它的定义，
    以此强调和了解一些常见的模式。
<div class="paragraph"> </div>

 在 Coq 里，从一个二元组中提取出值的基本方法是<b>模式匹配（pattern matching）</b>。
    另一种方法是使用 <span class="inlinecode"><span class="id" type="var">fst</span></span> 和 <span class="inlinecode"><span class="id" type="var">snd</span></span>——第一投影和第二投影操作子。
    我们在这里使用第二种方式。举个例子，下面的函数接受自然数的二元组作为参数，
    并返回他们和与差构成的二元组：
<pre>
       \x : Nat*Nat.
          let sum = x.fst + x.snd in
          let diff = x.fst - x.snd in
          (sum,diff)
</pre>

<div class="paragraph"> </div>

 为简单类型 lambda-演算添加二元组需要为项添加两种新的形式：创建二元组，写做
    <span class="inlinecode">(<span class="id" type="var">t<sub>1</sub></span>,<span class="id" type="var">t<sub>2</sub></span>)</span>；以及投影操作，写做 <span class="inlinecode"><span class="id" type="var">t.fst</span></span> 和 <span class="inlinecode"><span class="id" type="var">t.snd</span></span>，分别用于提取出第一个和
    第二个元素。我们还需要一个新的类型构造子，<span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span>*<span class="id" type="var">T<sub>2</sub></span></span> 作为 <span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span></span> 和 <span class="inlinecode"><span class="id" type="var">T<sub>2</sub></span></span>
    的<b>积（product）</b>。
<div class="paragraph"> </div>

 语法：
<pre>
       t <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                项
           | ...
           | (t,t)             二元组
           | t.fst             第一个元素
           | t.snd             第二个元素

       v <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                值
           | ...
           | (v,v)             二元组值

       T <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                类型
           | ...
           | T * T             积类型
</pre>

<div class="paragraph"> </div>

 我们需要几个新的归约规则来描述二元组和投影操作的行为。
<div class="paragraph"> </div>

<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">t<sub>1</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>1</sub>'</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_Pair1) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">(t<sub>1</sub>,t<sub>2</sub>)&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;(t<sub>1</sub>',t<sub>2</sub>)</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">t<sub>2</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>2</sub>'</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_Pair2) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">(v<sub>1</sub>,t<sub>2</sub>)&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;(v<sub>1</sub>,t<sub>2</sub>')</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">t<sub>1</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>1</sub>'</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_Fst1) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">t<sub>1</sub>.fst&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>1</sub>'.fst</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_FstPair) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">(v<sub>1</sub>,v<sub>2</sub>).fst&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;v<sub>1</sub></td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">t<sub>1</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>1</sub>'</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_Snd1) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">t<sub>1</sub>.snd&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>1</sub>'.snd</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_SndPair) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">(v<sub>1</sub>,v<sub>2</sub>).snd&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;v<sub>2</sub></td>
  <td></td>
</td>
</table></center>
<div class="paragraph"> </div>

 规则 <span class="inlinecode"><span class="id" type="var">ST_FstPair</span></span> 和 <span class="inlinecode"><span class="id" type="var">ST_SndPair</span></span> 是说，我们可以对完全归约的二元组
    取其第一个元素或第二个元素。同余规则 <span class="inlinecode"><span class="id" type="var">ST_Fst1</span></span> 和 <span class="inlinecode"><span class="id" type="var">ST_Snd1</span></span> 则是说，
    在被投影的二元组还没有完全归约时，我们可以在投影下允许对二元组归约。
    <span class="inlinecode"><span class="id" type="var">ST_Pair1</span></span> 和 <span class="inlinecode"><span class="id" type="var">ST_Pair2</span></span> 则对二元组的某一部分归约：分别是左边的部分，以及
    当左边的部分是值时对右边的部分归约。在这两个规则中，我们使用元变量
    <span class="inlinecode"><span class="id" type="var">v</span></span> 和 <span class="inlinecode"><span class="id" type="var">t</span></span> 来强制对二元组实现从左向右的求值策略。（请注意，其中隐含的约定是 <span class="inlinecode"><span class="id" type="var">v</span></span>
    或 <span class="inlinecode"><span class="id" type="var">v<sub>1</sub></span></span> 这样的元变量仅指值。）我们同样添加了对二元组值的定义，即 <span class="inlinecode">(<span class="id" type="var">v<sub>1</sub></span>,<span class="id" type="var">v<sub>2</sub></span>)</span>
    是一个值。二元组的成员必须是值，这一点保证了当二元组作为参数传入一个函数时已经
    完全归约了。
<div class="paragraph"> </div>

 二元组和投影的类型规则十分直接。 
<div class="paragraph"> </div>

<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t<sub>1</sub>&nbsp;&#x2208;&nbsp;T<sub>1</sub>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Gamma&nbsp;&#x22A2;&nbsp;t<sub>2</sub>&nbsp;&#x2208;&nbsp;T<sub>2</sub></td>
  <td class="infrulenamecol" rowspan="3">
    (T_Pair) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;(t<sub>1</sub>,t<sub>2</sub>)&nbsp;&#x2208;&nbsp;T<sub>1</sub>*T<sub>2</sub></td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t&nbsp;&#x2208;&nbsp;T<sub>1</sub>*T<sub>2</sub></td>
  <td class="infrulenamecol" rowspan="3">
    (T_Fst) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t.fst&nbsp;&#x2208;&nbsp;T<sub>1</sub></td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t&nbsp;&#x2208;&nbsp;T<sub>1</sub>*T<sub>2</sub></td>
  <td class="infrulenamecol" rowspan="3">
    (T_Snd) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t.snd&nbsp;&#x2208;&nbsp;T<sub>2</sub></td>
  <td></td>
</td>
</table></center>
<div class="paragraph"> </div>

 <span class="inlinecode"><span class="id" type="var">T_Pair</span></span> 是说如果 <span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> 有类型 <span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span></span> 且 <span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span> 有类型 <span class="inlinecode"><span class="id" type="var">T<sub>2</sub></span></span>，
    那么 <span class="inlinecode">(<span class="id" type="var">t<sub>1</sub></span>,<span class="id" type="var">t<sub>2</sub></span>)</span> 有类型 <span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span>*<span class="id" type="var">T<sub>2</sub></span></span> 。相反，<span class="inlinecode"><span class="id" type="var">T_Fst</span></span> 和 <span class="inlinecode"><span class="id" type="var">T_Snd</span></span> 告诉我们，
   如果 <span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> 为积类型 <span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span>*<span class="id" type="var">T<sub>2</sub></span></span>（即，如果 <span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> 会归约为一个二元组），
   那么二元组的投影的类型为 <span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span></span> 和 <span class="inlinecode"><span class="id" type="var">T<sub>2</sub></span></span>。
<div class="paragraph"> </div>

<a name="lab250"></a><h2 class="section">单元素类型</h2>

<div class="paragraph"> </div>

 另一个在 ML 语言家族中经常出现的基础类型是只含有一个元素的类型（singleton type），即 <span class="inlinecode"><span class="id" type="var">Unit</span></span>。 它只含有一个常量项 <span class="inlinecode"><span class="id" type="var">unit</span></span>（以小写 <span class="inlinecode"><span class="id" type="var">u</span></span> 开头），以及一个类型规则使 <span class="inlinecode"><span class="id" type="var">unit</span></span> 成为
    <span class="inlinecode"><span class="id" type="var">Unit</span></span> 的一个元素。我们同时添加 <span class="inlinecode"><span class="id" type="var">unit</span></span> 到可作为值的项的集合中，确实，<span class="inlinecode"><span class="id" type="var">unit</span></span>
    是 <span class="inlinecode"><span class="id" type="var">Unit</span></span> 类型的表达式唯一可能的归约结果。 
<div class="paragraph"> </div>

 语法：
<pre>
       t <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                Terms
           | ...               (other terms same as before)
           | unit              unit

       v <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                Values
           | ...
           | unit              unit value

       T <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                Types
           | ...
           | Unit              unit type
</pre>
    定型规则：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (T_Unit) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;unit&nbsp;&#x2208;&nbsp;Unit</td>
  <td></td>
</td>
</table></center>
<div class="paragraph"> </div>

 看起来似乎有些奇怪，我们为什么要定义只含有一个元素的类型呢？
    毕竟，难道不是每个计算都不会在这样的类型中居留吗？

<div class="paragraph"> </div>

    这是个好问题，而且确实在 STLC 中 <span class="inlinecode"><span class="id" type="var">Unit</span></span> 类型并不是特别重要（尽管后面我们会看
    到它的两个用处）。在更丰富的语言中，使用 <span class="inlinecode"><span class="id" type="var">Unit</span></span> 类型来处理<b>副作用（side effect）</b>
    会很方便，例如改写变量或指针的赋值语句、异常以及其他非局部控制结构等情形。
    在这样的语言中，<span class="inlinecode"><span class="id" type="var">Unit</span></span> 类型为仅有副作用的表达式提供了一个方便的类型。
<div class="paragraph"> </div>

<a name="lab251"></a><h2 class="section">和类型</h2>

<div class="paragraph"> </div>

 一些程序需要处理具有两种不同形式的值。比如说，在一个大学数据库中中我们想要根据名字
    <b>或</b>识别号码来搜索某个学生。这个搜索函数可以返回匹配到的值，<b>或</b>返回一个错误代码。

<div class="paragraph"> </div>

    有很多二元<b>和类型（sum type）</b>（有时候也叫做<b>不交并（disjoint union）</b>）
    的具体例子，他们描述了从一个或两个给定类型的值的集合，例如：
<pre>
       Nat + Bool
</pre>

<div class="paragraph"> </div>

    我们在创建这些类型的值时，会为值<b>标记（tagging）</b>上其成分类型。
    比如说，如果 <span class="inlinecode"><span class="id" type="var">n</span></span> 是自然数，那么 <span class="inlinecode"><span class="id" type="var">inl</span></span> <span class="inlinecode"><span class="id" type="var">n</span></span> 是 <span class="inlinecode"><span class="id" type="var">Nat</span>+<span class="id" type="var">Bool</span></span> 的一个元素；
    类似地，如果 <span class="inlinecode"><span class="id" type="var">b</span></span> 的类型为 <span class="inlinecode"><span class="id" type="var">Bool</span></span>，那么 <span class="inlinecode"><span class="id" type="var">inr</span></span> <span class="inlinecode"><span class="id" type="var">b</span></span> 是 <span class="inlinecode"><span class="id" type="var">Nat</span>+<span class="id" type="var">Bool</span></span>
    的一个元素。
    如果把标签 <span class="inlinecode"><span class="id" type="var">inl</span></span> 和 <span class="inlinecode"><span class="id" type="var">inr</span></span> 看作函数，其类型解释了他们的名字：
<pre>
       inl &#x2208; Nat  <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> Nat + Bool
       inr &#x2208; Bool <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> Nat + Bool
</pre>
    这两个函数分别将 <span class="inlinecode"><span class="id" type="var">Nat</span></span> 或 <span class="inlinecode"><span class="id" type="var">Bool</span></span> 的元素“注入”进和类型 <span class="inlinecode"><span class="id" type="var">Nat</span>+<span class="id" type="var">Bool</span></span>
    的左成分或右成分中。（但其实我们不必将其作为函数形式化：<span class="inlinecode"><span class="id" type="var">inl</span></span> 和 <span class="inlinecode"><span class="id" type="var">inr</span></span>
    是关键字，而且  <span class="inlinecode"><span class="id" type="var">inl</span></span> <span class="inlinecode"><span class="id" type="var">t</span></span> 和 <span class="inlinecode"><span class="id" type="var">inr</span></span> <span class="inlinecode"><span class="id" type="var">t</span></span> 是基本的语法形式，而非函数应用。） 
<div class="paragraph"> </div>

 一般来说，被 <span class="inlinecode"><span class="id" type="var">inl</span></span> 标记的 <span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span></span> 的元素加上被 <span class="inlinecode"><span class="id" type="var">inr</span></span>
    标记的 <span class="inlinecode"><span class="id" type="var">T<sub>2</sub></span></span> 的元素一同构成了 <span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span></span> <span class="inlinecode">+</span> <span class="inlinecode"><span class="id" type="var">T<sub>2</sub></span></span> 的元素。 
<div class="paragraph"> </div>

 我们之前在 Coq 编程中见过，和类型的一个重要用途是传递错误：
<pre>
      div &#x2208; Nat <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> Nat <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (Nat + Unit)
      div =
        \x:Nat. \y:Nat.
          test iszero y then
            inr unit
          else
            inl ...
</pre>
 事实上，上面的 <span class="inlinecode"><span class="id" type="var">Nat</span></span> <span class="inlinecode">+</span> <span class="inlinecode"><span class="id" type="var">Unit</span></span> 类型与 Coq 中的 <span class="inlinecode"><span class="id" type="var">option</span></span> <span class="inlinecode"><span class="id" type="var">nat</span></span>
    类型是同构的——也即，我们很容易写出他们的转换函数。 
<div class="paragraph"> </div>

 为了<b>使用</b>和类型和元素，我们引入 <span class="inlinecode"><span class="id" type="tactic">case</span></span> 语句（Coq 中 <span class="inlinecode"><span class="id" type="keyword">match</span></span>
    的非常简化版）用于解构他们。比如说，下面的程序将 <span class="inlinecode"><span class="id" type="var">Nat</span>+<span class="id" type="var">Bool</span></span> 的值转为了 <span class="inlinecode"><span class="id" type="var">Nat</span></span>：
<div class="paragraph"> </div>

<pre>
    getNat &#x2208; Nat+Bool <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> Nat
    getNat =
      \x:Nat+Bool.
        case x of
          inl n =&gt; n
        | inr b =&gt; test b then 1 else 0
</pre>
 更加形式化地讲…… 
<div class="paragraph"> </div>

 语法：
<pre>
       t <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                项
           | ...               （和前面一样的其它项）
           | inl T t           左标记
           | inr T t           右标记
           | case t of         模式匹配
               inl x =&gt; t
             | inr x =&gt; t

       v <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                值
           | ...
           | inl T v           标记过的值（左）
           | inr T v           标记过的值（右）

       T <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                类型
           | ...
           | T + T             和类型
</pre>

<div class="paragraph"> </div>

 归约规则：

<div class="paragraph"> </div>

<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">t<sub>1</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>1</sub>'</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_Inl) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">inl&nbsp;T<sub>2</sub>&nbsp;t<sub>1</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;inl&nbsp;T<sub>2</sub>&nbsp;t<sub>1</sub>'</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">t<sub>2</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>2</sub>'</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_Inr) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">inr&nbsp;T<sub>1</sub>&nbsp;t<sub>2</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;inr&nbsp;T<sub>1</sub>&nbsp;t<sub>2</sub>'</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">t<sub>0</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>0</sub>'</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_Case) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">case&nbsp;t<sub>0</sub>&nbsp;of&nbsp;inl&nbsp;x<sub>1</sub>&nbsp;⇒&nbsp;t<sub>1</sub>&nbsp;|&nbsp;inr&nbsp;x<sub>2</sub>&nbsp;⇒&nbsp;t<sub>2</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">case&nbsp;t<sub>0</sub>'&nbsp;of&nbsp;inl&nbsp;x<sub>1</sub>&nbsp;⇒&nbsp;t<sub>1</sub>&nbsp;|&nbsp;inr&nbsp;x<sub>2</sub>&nbsp;⇒&nbsp;t<sub>2</sub></td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_CaseInl) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">case&nbsp;(inl&nbsp;T<sub>2</sub>&nbsp;v<sub>1</sub>)&nbsp;of&nbsp;inl&nbsp;x<sub>1</sub>&nbsp;⇒&nbsp;t<sub>1</sub>&nbsp;|&nbsp;inr&nbsp;x<sub>2</sub>&nbsp;⇒&nbsp;t<sub>2</sub></td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;&nbsp;[x<sub>1</sub>:=v<sub>1</sub>]t<sub>1</sub></td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_CaseInr) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">case&nbsp;(inr&nbsp;T<sub>1</sub>&nbsp;v<sub>2</sub>)&nbsp;of&nbsp;inl&nbsp;x<sub>1</sub>&nbsp;⇒&nbsp;t<sub>1</sub>&nbsp;|&nbsp;inr&nbsp;x<sub>2</sub>&nbsp;⇒&nbsp;t<sub>2</sub></td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;&nbsp;[x<sub>2</sub>:=v<sub>1</sub>]t<sub>2</sub></td>
  <td></td>
</td>
</table></center>
<div class="paragraph"> </div>

 定型规则：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t<sub>1</sub>&nbsp;&#x2208;&nbsp;T<sub>1</sub></td>
  <td class="infrulenamecol" rowspan="3">
    (T_Inl) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;inl&nbsp;T<sub>2</sub>&nbsp;t<sub>1</sub>&nbsp;&#x2208;&nbsp;T<sub>1</sub>&nbsp;+&nbsp;T<sub>2</sub></td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t<sub>2</sub>&nbsp;&#x2208;&nbsp;T<sub>2</sub></td>
  <td class="infrulenamecol" rowspan="3">
    (T_Inr) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;inr&nbsp;T<sub>1</sub>&nbsp;t<sub>2</sub>&nbsp;&#x2208;&nbsp;T<sub>1</sub>&nbsp;+&nbsp;T<sub>2</sub></td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t&nbsp;&#x2208;&nbsp;T<sub>1</sub>+T<sub>2</sub></td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">x<sub>1</sub><span class="nowrap"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span></span>T<sub>1</sub>;&nbsp;Gamma&nbsp;&#x22A2;&nbsp;t<sub>1</sub>&nbsp;&#x2208;&nbsp;T</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">x<sub>2</sub><span class="nowrap"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span></span>T<sub>2</sub>;&nbsp;Gamma&nbsp;&#x22A2;&nbsp;t<sub>2</sub>&nbsp;&#x2208;&nbsp;T</td>
  <td class="infrulenamecol" rowspan="3">
    (T_Case) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;case&nbsp;t&nbsp;of&nbsp;inl&nbsp;x<sub>1</sub>&nbsp;⇒&nbsp;t<sub>1</sub>&nbsp;|&nbsp;inr&nbsp;x<sub>2</sub>&nbsp;⇒&nbsp;t<sub>2</sub>&nbsp;&#x2208;&nbsp;T</td>
  <td></td>
</td>
</table></center>    为了让类型关系简单一点，在 <span class="inlinecode"><span class="id" type="var">inl</span></span> 和 <span class="inlinecode"><span class="id" type="var">inr</span></span> 规则中我们使用了类型注释，我们在处理
    函数的类型时也是这么做的。
<div class="paragraph"> </div>

 如果没有这额外的类型信息，一旦我们确定了 <span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> 为类型 <span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span></span>，类型规则
    <span class="inlinecode"><span class="id" type="var">T_Inl</span></span> 则必须有能力为 <span class="inlinecode"><span class="id" type="var">inl</span></span> <span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> 推导出类型 <span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span></span> <span class="inlinecode">+</span> <span class="inlinecode"><span class="id" type="var">T<sub>2</sub></span></span>，而其中 <span class="inlinecode"><span class="id" type="var">T<sub>2</sub></span></span>
    可为任意类型。比如说，我们可以同时推导出 <span class="inlinecode"><span class="id" type="var">inl</span></span> <span class="inlinecode">5</span> <span class="inlinecode">:</span> <span class="inlinecode"><span class="id" type="var">Nat</span></span> <span class="inlinecode">+</span> <span class="inlinecode"><span class="id" type="var">Nat</span></span> 和
    <span class="inlinecode"><span class="id" type="var">inl</span></span> <span class="inlinecode">5</span> <span class="inlinecode">:</span> <span class="inlinecode"><span class="id" type="var">Nat</span></span> <span class="inlinecode">+</span> <span class="inlinecode"><span class="id" type="var">Bool</span></span>（以及无数个这样的类型）。这一特性（技术上说，
    是类型唯一性的丧失）意味着我们无法像之前处理其他特性那样仅仅通过“自底向上地
    阅读类型规则”来构造出类型检查的算法。

<div class="paragraph"> </div>

    有很多种方式处理这个难题。最简单的方法，也是我们在这里采用的，就是要求程序员
    在注入时显式地提供和类型“另一侧”的类型。这对程序员会产生一些负担（因此很多
    现实语言采用了其他方法），但这种方法易于理解和形式化。
<div class="paragraph"> </div>

<a name="lab252"></a><h2 class="section">列表</h2>

<div class="paragraph"> </div>

 我们可以将之前学过的类型归结为两类：例如 <span class="inlinecode"><span class="id" type="var">Bool</span></span> 这样的<b>基本类型</b>；
    以及例如 <span class="inlinecode">→</span> 和 <span class="inlinecode">*</span> 这样的<b>类型构造子</b>，用于从已有的类型构造新的类型。
    另一个非常有用的类型构造子是 <span class="inlinecode"><span class="id" type="var">List</span></span>。对于每个类型 <span class="inlinecode"><span class="id" type="var">T</span></span>，类型 <span class="inlinecode"><span class="id" type="var">List</span></span> <span class="inlinecode"><span class="id" type="var">T</span></span>
    表示元素类型为 <span class="inlinecode"><span class="id" type="var">T</span></span> 的有限长列表。

<div class="paragraph"> </div>

    原则上，我们可以用二元组、和类型与<b>递归</b>类型编码出列表。但为递归类型给出
    其语义并不直接。因此，我们直接将列表作为一个特殊类型加以讨论。

<div class="paragraph"> </div>

    下面我们给出列表的语法，语义和类型规则。这些列表操作基本与 Coq 中的相同，
    除了 <span class="inlinecode"><span class="id" type="var">nil</span></span> 中类型注解是强制的，而 <span class="inlinecode"><span class="id" type="var">cons</span></span> 而不需要类型注解。我们使用 <span class="inlinecode"><span class="id" type="var">lcase</span></span>
    来解构列表，以此可以用于提取出列表的 <span class="inlinecode"><span class="id" type="var">head</span></span> 等。
<div class="paragraph"> </div>

 例如，下面的函数计算了一个数值列表的前两个元素之和：
<pre>
      \x:List Nat.
      lcase x of nil   =&gt; 0
               | a::x' =&gt; lcase x' of nil    =&gt; a
                                    | b::x'' =&gt; a+b
</pre>

<div class="paragraph"> </div>

    语法：
<pre>
       t <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                项
           | ...
           | nil T
           | cons t t
           | lcase t of nil  =&gt; t
                      | x::x =&gt; t

       v <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                值
           | ...
           | nil T             nil 值
           | cons v v          cons 值

       T <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                类型
           | ...
           | List T            T 类型列表
</pre>

<div class="paragraph"> </div>

 归约规则：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">t<sub>1</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>1</sub>'</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_Cons1) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">cons&nbsp;t<sub>1</sub>&nbsp;t<sub>2</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;cons&nbsp;t<sub>1</sub>'&nbsp;t<sub>2</sub></td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">t<sub>2</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>2</sub>'</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_Cons2) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">cons&nbsp;v<sub>1</sub>&nbsp;t<sub>2</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;cons&nbsp;v<sub>1</sub>&nbsp;t<sub>2</sub>'</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">t<sub>1</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>1</sub>'</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_Lcase1) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">(lcase&nbsp;t<sub>1</sub>&nbsp;of&nbsp;nil&nbsp;⇒&nbsp;t<sub>2</sub>&nbsp;|&nbsp;xh::xt&nbsp;⇒&nbsp;t<sub>3</sub>)&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">(lcase&nbsp;t<sub>1</sub>'&nbsp;of&nbsp;nil&nbsp;⇒&nbsp;t<sub>2</sub>&nbsp;|&nbsp;xh::xt&nbsp;⇒&nbsp;t<sub>3</sub>)</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_LcaseNil) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">(lcase&nbsp;nil&nbsp;T&nbsp;of&nbsp;nil&nbsp;⇒&nbsp;t<sub>2</sub>&nbsp;|&nbsp;xh::xt&nbsp;⇒&nbsp;t<sub>3</sub>)</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>2</sub></td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_LcaseCons) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">(lcase&nbsp;(cons&nbsp;vh&nbsp;vt)&nbsp;of&nbsp;nil&nbsp;⇒&nbsp;t<sub>2</sub>&nbsp;|&nbsp;xh::xt&nbsp;⇒&nbsp;t<sub>3</sub>)</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;[xh:=vh,xt:=vt]t<sub>3</sub></td>
  <td></td>
</td>
</table></center>
<div class="paragraph"> </div>

 定型规则：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (T_Nil) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;nil&nbsp;T&nbsp;&#x2208;&nbsp;List&nbsp;T</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t<sub>1</sub>&nbsp;&#x2208;&nbsp;T&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Gamma&nbsp;&#x22A2;&nbsp;t<sub>2</sub>&nbsp;&#x2208;&nbsp;List&nbsp;T</td>
  <td class="infrulenamecol" rowspan="3">
    (T_Cons) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;cons&nbsp;t<sub>1</sub>&nbsp;t<sub>2</sub>&nbsp;&#x2208;&nbsp;List&nbsp;T</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t<sub>1</sub>&nbsp;&#x2208;&nbsp;List&nbsp;T<sub>1</sub></td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t<sub>2</sub>&nbsp;&#x2208;&nbsp;T</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">(h<span class="nowrap"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span></span>T<sub>1</sub>;&nbsp;t<span class="nowrap"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span></span>List&nbsp;T<sub>1</sub>;&nbsp;Gamma)&nbsp;&#x22A2;&nbsp;t<sub>3</sub>&nbsp;&#x2208;&nbsp;T</td>
  <td class="infrulenamecol" rowspan="3">
    (T_Lcase) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;(lcase&nbsp;t<sub>1</sub>&nbsp;of&nbsp;nil&nbsp;⇒&nbsp;t<sub>2</sub>&nbsp;|&nbsp;h::t&nbsp;⇒&nbsp;t<sub>3</sub>)&nbsp;&#x2208;&nbsp;T</td>
  <td></td>
</td>
</table></center>
<div class="paragraph"> </div>

<a name="lab253"></a><h2 class="section">一般递归</h2>

<div class="paragraph"> </div>

 另一个在多数语言（包括 Coq）中都会出现的功能是定义递归函数。例如，我们可以用
    如下方式定义阶乘函数：
<pre>
      fact = \x:Nat.
                test x=0 then 1 else x * (fact (pred x)))
</pre>
   请注意绑定的右侧使用了绑定左侧的变量名——这在我们之前的 <span class="inlinecode"><span class="id" type="keyword">let</span></span> 中是不被允许的。

<div class="paragraph"> </div>

   直接形式化这种“递归定义”机制是可行的，但也需要一些额外的努力：特别是，在 <span class="inlinecode"><span class="id" type="var">step</span></span>
   关系中，我们需要给递归函数的定义传递一个“环境”。
<div class="paragraph"> </div>

 还有另外一种有点啰嗦但一样强大的方式来形式化递归函数，
    这种方式更加直接：我们不直接写递归的定义，而是定义一个叫做 <span class="inlinecode"><span class="id" type="var">fix</span></span>
    的<b>不动点算子（fixed-point operator）</b>，它会在归约时“展开”定义右侧表达式中
    出现的递归定义。

<div class="paragraph"> </div>

    比如说，以下程序
<pre>
      fact = \x:Nat.
                test x=0 then 1 else x * (fact (pred x)))
</pre>
    可以改写为：
<pre>
      fact =
          fix
            (\f:Nat<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>Nat.
               \x:Nat.
                  test x=0 then 1 else x * (f (pred x)))
</pre>
 我们可用如下方式把前者转换为后者：

<div class="paragraph"> </div>

<ul class="doclist">
<li> 在 <span class="inlinecode"><span class="id" type="var">fact</span></span> 的定义的右侧表达式中，替换递归引用的 <span class="inlinecode"><span class="id" type="var">fact</span></span> 为一个新的变量 <span class="inlinecode"><span class="id" type="var">f</span></span>。

<div class="paragraph"> </div>


</li>
<li> 在最开始为抽象添加一个参数 <span class="inlinecode"><span class="id" type="var">f</span></span>，以及其合适的类型注解。（因为我们用 <span class="inlinecode"><span class="id" type="var">f</span></span>
        替换了类型为 <span class="inlinecode"><span class="id" type="var">Nat</span>→<span class="id" type="var">Nat</span></span> 的 <span class="inlinecode"><span class="id" type="var">fact</span></span>，我们也要求 <span class="inlinecode"><span class="id" type="var">f</span></span> 有相同的类型。）
        新的抽象有类型 <span class="inlinecode">(<span class="id" type="var">Nat</span>→<span class="id" type="var">Nat</span>)</span> <span class="inlinecode">→</span> <span class="inlinecode">(<span class="id" type="var">Nat</span>→<span class="id" type="var">Nat</span>)</span>。

<div class="paragraph"> </div>


</li>
<li> 对这个抽象应用 <span class="inlinecode"><span class="id" type="var">fix</span></span>。这个应用的类型为 <span class="inlinecode"><span class="id" type="var">Nat</span>→<span class="id" type="var">Nat</span></span>。

<div class="paragraph"> </div>


</li>
<li> 在其他地方，像使用普通的 <span class="inlinecode"><span class="id" type="keyword">let</span></span> 绑定一样使用 <span class="inlinecode"><span class="id" type="var">fact</span></span>。

</li>
</ul>

<div class="paragraph"> </div>

 可以把被传入 <span class="inlinecode"><span class="id" type="var">fix</span></span> 的高阶函数 <span class="inlinecode"><span class="id" type="var">f</span></span> 理解为一个 <span class="inlinecode"><span class="id" type="var">fact</span></span> 函数的<b>生成器（generator）</b>：
    如果 <span class="inlinecode"><span class="id" type="var">f</span></span> 被应用于一个函数，且这个函数“近似地”描述了 <span class="inlinecode"><span class="id" type="var">fact</span></span> 对至多某个数 <span class="inlinecode"><span class="id" type="var">n</span></span> 的行为
    （也即，一个仅会对小于或等于 <span class="inlinecode"><span class="id" type="var">n</span></span> 的输入上返回正确结果的函数，但是我们并不在乎其在大于
    <span class="inlinecode"><span class="id" type="var">n</span></span> 的输入上的结果），那么 <span class="inlinecode"><span class="id" type="var">f</span></span> 返回一个稍微好一点的 <span class="inlinecode"><span class="id" type="var">fact</span></span> 的近似——一个对至多
    <span class="inlinecode"><span class="id" type="var">n</span>+1</span> 会返回正确结果的函数。对这个生成器应用 <span class="inlinecode"><span class="id" type="var">fix</span></span> 会返回它的<b>不动点</b>，也即一个对
    所有输入 <span class="inlinecode"><span class="id" type="var">n</span></span> 都有正确结果的函数。

<div class="paragraph"> </div>

    （“不动点”在这里的含义与数学上的不动点是完全相同的，也即函数 <span class="inlinecode"><span class="id" type="var">f</span></span> 的一个不动点
    是对于输入 <span class="inlinecode"><span class="id" type="var">x</span></span> 有 <span class="inlinecode"><span class="id" type="var">f</span>(<span class="id" type="var">x</span>)</span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">x</span></span>。这里，类型为 <span class="inlinecode">(<span class="id" type="var">Nat</span>→<span class="id" type="var">Nat</span>)<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>(<span class="id" type="var">Nat</span>→<span class="id" type="var">Nat</span>)</span>
    的函数 <span class="inlinecode"><span class="id" type="var">F</span></span> 的一个不动点是类型为 <span class="inlinecode"><span class="id" type="var">Nat</span>→<span class="id" type="var">Nat</span></span> 的函数 <span class="inlinecode"><span class="id" type="var">f</span></span>，使得 <span class="inlinecode"><span class="id" type="var">F</span></span> <span class="inlinecode"><span class="id" type="var">f</span></span> 与 <span class="inlinecode"><span class="id" type="var">f</span></span>
    的行为完全相同。） 
<div class="paragraph"> </div>

 语法：
<pre>
       t <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                项
           | ...
           | fix t             不动点算子
</pre>
   归约规则：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">t<sub>1</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>1</sub>'</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_Fix1) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">fix&nbsp;t<sub>1</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;fix&nbsp;t<sub>1</sub>'</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_FixAbs) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">fix&nbsp;(\xf:T<sub>1</sub>.t2)&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;[xf:=fix&nbsp;(\xf:T<sub>1</sub>.t2)]&nbsp;t<sub>2</sub></td>
  <td></td>
</td>
</table></center>   定型规则：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t<sub>1</sub>&nbsp;&#x2208;&nbsp;T<sub>1</sub><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>T<sub>1</sub></td>
  <td class="infrulenamecol" rowspan="3">
    (T_Fix) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;fix&nbsp;t<sub>1</sub>&nbsp;&#x2208;&nbsp;T<sub>1</sub></td>
  <td></td>
</td>
</table></center> 
<div class="paragraph"> </div>

 让我们以 <span class="inlinecode"><span class="id" type="var">fact</span></span> <span class="inlinecode">3</span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">fix</span></span> <span class="inlinecode"><span class="id" type="var">F</span></span> <span class="inlinecode">3</span> 为例看看 <span class="inlinecode"><span class="id" type="var">ST_FixAbs</span></span> 是如何工作的，其中
<pre>
    F = (\f. \x. test x=0 then 1 else x * (f (pred x)))
</pre>
    （简洁起见，我们省略了类型注解）。
<pre>
    fix F 3
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_FixAbs</span></span> + <span class="inlinecode"><span class="id" type="var">ST_App1</span></span>
<pre>
    (\x. test x=0 then 1 else x * (fix F (pred x))) 3
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_AppAbs</span></span>
<pre>
    test 3=0 then 1 else 3 * (fix F (pred 3))
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_Test0_Nonzero</span></span>
<pre>
    3 * (fix F (pred 3))
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_FixAbs</span></span> <span class="inlinecode">+</span> <span class="inlinecode"><span class="id" type="var">ST_Mult2</span></span>
<pre>
    3 * ((\x. test x=0 then 1 else x * (fix F (pred x))) (pred 3))
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_PredNat</span></span> <span class="inlinecode">+</span> <span class="inlinecode"><span class="id" type="var">ST_Mult2</span></span> <span class="inlinecode">+</span> <span class="inlinecode"><span class="id" type="var">ST_App2</span></span>
<pre>
    3 * ((\x. test x=0 then 1 else x * (fix F (pred x))) 2)
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_AppAbs</span></span> <span class="inlinecode">+</span> <span class="inlinecode"><span class="id" type="var">ST_Mult2</span></span>
<pre>
    3 * (test 2=0 then 1 else 2 * (fix F (pred 2)))
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_Test0_Nonzero</span></span> <span class="inlinecode">+</span> <span class="inlinecode"><span class="id" type="var">ST_Mult2</span></span>
<pre>
    3 * (2 * (fix F (pred 2)))
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_FixAbs</span></span> <span class="inlinecode">+</span> <span class="inlinecode">2</span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">ST_Mult2</span></span>
<pre>
    3 * (2 * ((\x. test x=0 then 1 else x * (fix F (pred x))) (pred 2)))
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_PredNat</span></span> <span class="inlinecode">+</span> <span class="inlinecode">2</span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">ST_Mult2</span></span> <span class="inlinecode">+</span> <span class="inlinecode"><span class="id" type="var">ST_App2</span></span>
<pre>
    3 * (2 * ((\x. test x=0 then 1 else x * (fix F (pred x))) 1))
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_AppAbs</span></span> <span class="inlinecode">+</span> <span class="inlinecode">2</span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">ST_Mult2</span></span>
<pre>
    3 * (2 * (test 1=0 then 1 else 1 * (fix F (pred 1))))
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_Test0_Nonzero</span></span> <span class="inlinecode">+</span> <span class="inlinecode">2</span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">ST_Mult2</span></span>
<pre>
    3 * (2 * (1 * (fix F (pred 1))))
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_FixAbs</span></span> <span class="inlinecode">+</span> <span class="inlinecode">3</span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">ST_Mult2</span></span>
<pre>
    3 * (2 * (1 * ((\x. test x=0 then 1 else x * (fix F (pred x))) (pred 1))))
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_PredNat</span></span> <span class="inlinecode">+</span> <span class="inlinecode">3</span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">ST_Mult2</span></span> <span class="inlinecode">+</span> <span class="inlinecode"><span class="id" type="var">ST_App2</span></span>
<pre>
    3 * (2 * (1 * ((\x. test x=0 then 1 else x * (fix F (pred x))) 0)))
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_AppAbs</span></span> <span class="inlinecode">+</span> <span class="inlinecode">3</span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">ST_Mult2</span></span>
<pre>
    3 * (2 * (1 * (test 0=0 then 1 else 0 * (fix F (pred 0)))))
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_Test0Zero</span></span> <span class="inlinecode">+</span> <span class="inlinecode">3</span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">ST_Mult2</span></span>
<pre>
    3 * (2 * (1 * 1))
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_MultNats</span></span> <span class="inlinecode">+</span> <span class="inlinecode">2</span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">ST_Mult2</span></span>
<pre>
    3 * (2 * 1)
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_MultNats</span></span> <span class="inlinecode">+</span> <span class="inlinecode"><span class="id" type="var">ST_Mult2</span></span>
<pre>
    3 * 2
</pre>
<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">ST_MultNats</span></span>
<pre>
    6
</pre>

<div class="paragraph"> </div>

 特别重要的一点是，不同于 Coq 中的 <span class="inlinecode"><span class="id" type="keyword">Fixpoint</span></span> 定义，
    <span class="inlinecode"><span class="id" type="var">fix</span></span> 并不会保证所定义的函数一定停机。
<div class="paragraph"> </div>

<a name="lab254"></a><h4 class="section">练习：1 星, standard, optional (halve_fix)</h4>
 请将下面非形式化的定义使用 <span class="inlinecode"><span class="id" type="var">fix</span></span> 写出：
<pre>
      halve =
        \x:Nat.
           test x=0 then 0
           else test (pred x)=0 then 0
           else 1 + (halve (pred (pred x)))
</pre>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
 <span class="proofbox">&#9744;</span> 
<div class="paragraph"> </div>

<a name="lab255"></a><h4 class="section">练习：1 星, standard, optional (fact_steps)</h4>
 请分步骤写下 <span class="inlinecode"><span class="id" type="var">fact</span></span> <span class="inlinecode">1</span> 如何归约为正规式（假定有一般算数操作的归约规则）。

<div class="paragraph"> </div>

    <span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
 <span class="proofbox">&#9744;</span> 
<div class="paragraph"> </div>

 对任意类型 <span class="inlinecode"><span class="id" type="var">T</span></span>，构造类型为 <span class="inlinecode"><span class="id" type="var">T</span>→<span class="id" type="var">T</span></span> 的函数的不动点的能力带了了一些令人惊讶的推论。
    特别是，这意味着<b>每个</b>类型都存在某个项。我们可以观察到，对每个类型 <span class="inlinecode"><span class="id" type="var">T</span></span>，
    我们可以定义项

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">fix</span>&nbsp;(\<span class="id" type="var">x</span>:<span class="id" type="var">T.x</span>)
<div class="paragraph"> </div>

</div>
    由规则 <span class="inlinecode"><span class="id" type="var">T_Fix</span></span> 和 <span class="inlinecode"><span class="id" type="var">T_Abs</span></span>，这个项的类型为 <span class="inlinecode"><span class="id" type="var">T</span></span>。由规则 <span class="inlinecode"><span class="id" type="var">ST_FixAbs</span></span>，
    这个项重复地归约为它自身。因此，它是类型 <span class="inlinecode"><span class="id" type="var">T</span></span> 的<b>不停机项（diverging element）</b>。

<div class="paragraph"> </div>

    从更为实用的角度，下面提供一个使用 <span class="inlinecode"><span class="id" type="var">fix</span></span> 定义两个参数的递归函数：
<pre>
    equal =
      fix
        (\eq:Nat<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>Nat<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>Bool.
           \m:Nat. \n:Nat.
             test m=0 then iszero n
             else test n=0 then fls
             else eq (pred m) (pred n))
</pre>
 最后的例子展示了如何用 <span class="inlinecode"><span class="id" type="var">fix</span></span> 定一个<b>二元组</b>的递归函数（规则 <span class="inlinecode"><span class="id" type="var">T_Fix</span></span>
    中的 <span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span></span> 并不需要函数类型）：
<pre>
      evenodd =
        fix
          (\eo: (Nat<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>Bool * Nat<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>Bool).
             let e = \n:Nat. test n=0 then tru else eo.snd (pred n) in
             let o = \n:Nat. test n=0 then fls else eo.fst (pred n) in
             (e,o))

      even = evenodd.fst
      odd  = evenodd.snd
</pre>

</div>

<div class="doc">
<a name="lab256"></a><h2 class="section">字段组</h2>

<div class="paragraph"> </div>

 作为 STLC 最后的一个基础扩展，让我们简要地学习一下如何定义<b>字段组（record）</b>
    及其类型。直观地说，字段组可以通过从两个方面一般化二元组来得到：他们是 n
    元（而不仅仅是二元）的而且可以通过<b>标签（label）</b>（而不仅仅是位置）来访问字段。 
<div class="paragraph"> </div>

 Syntax:
<pre>
       t <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                          Terms
           | ...
           | {i<sub>1</sub>=t<sub>1</sub>, ..., in=tn}         record
           | t.i                         projection

       v <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                          Values
           | ...
           | {i<sub>1</sub>=v<sub>1</sub>, ..., in=vn}         record value

       T <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>                          Types
           | ...
           | {i<sub>1</sub>:T<sub>1</sub>, ..., in:Tn}         record type
</pre>

<div class="paragraph"> </div>

 对二元组的一般化是很容易的。但是需要提醒的是，这里描述的方式要比之前章节中的
   非形式语法<b>更加</b>非形式：我们多处使用了“<span class="inlinecode">...</span>”来描述“任意数量的某项”，
   我们还省略了“字段组的标签不应当重复”这个附加条件。
<div class="paragraph"> </div>


<div class="paragraph"> </div>

   归约规则：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">ti&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;ti'</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_Rcd) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">{i<sub>1</sub>=v<sub>1</sub>,&nbsp;...,&nbsp;im=vm,&nbsp;in=ti&nbsp;,&nbsp;...}</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;{i<sub>1</sub>=v<sub>1</sub>,&nbsp;...,&nbsp;im=vm,&nbsp;in=ti',&nbsp;...}</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">t<sub>1</sub>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>1</sub>'</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_Proj1) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">t<sub>1</sub>.i&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;t<sub>1</sub>'.i</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (ST_ProjRcd) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">{...,&nbsp;i=vi,&nbsp;...}.i&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;vi</td>
  <td></td>
</td>
</table></center> 再次提醒，这些规则是非形式化的。比如说，第一个规则应当被读做“如果 <span class="inlinecode"><span class="id" type="var">ti</span></span>
   是最左边的非值字段，且如果 <span class="inlinecode"><span class="id" type="var">ti</span></span> 前进一步归约到 <span class="inlinecode"><span class="id" type="var">ti'</span></span>，那么整个字段组归约为……”。
   最后一个规则的意思是说应当只有一个名字为 <span class="inlinecode"><span class="id" type="var">i</span></span> 的字段，而其他的字段必须指向值。
<div class="paragraph"> </div>


<div class="paragraph"> </div>

   类型规则同样简单：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t<sub>1</sub>&nbsp;&#x2208;&nbsp;T<sub>1</sub>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Gamma&nbsp;&#x22A2;&nbsp;tn&nbsp;&#x2208;&nbsp;Tn</td>
  <td class="infrulenamecol" rowspan="3">
    (T_Rcd) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;{i<sub>1</sub>=t<sub>1</sub>,&nbsp;...,&nbsp;in=tn}&nbsp;&#x2208;&nbsp;{i<sub>1</sub>:T<sub>1</sub>,&nbsp;...,&nbsp;in:Tn}</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t&nbsp;&#x2208;&nbsp;{...,&nbsp;i:Ti,&nbsp;...}</td>
  <td class="infrulenamecol" rowspan="3">
    (T_Proj) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule">Gamma&nbsp;&#x22A2;&nbsp;t.i&nbsp;&#x2208;&nbsp;Ti</td>
  <td></td>
</td>
</table></center>
<div class="paragraph"> </div>

 有许多种方式来形式化上面的描述。

<div class="paragraph"> </div>

<ul class="doclist">
<li> 我们可以直接形式化语法结构和推断规则，并尽量与我们上面给出的非形式化描述保持相同。
        这在概念上来讲十分直接，当我们开发一个真正的编译器时，也会是我们的选择（特别是，
        它允许我们给出程序员易读的错误信息）。但是这些形式化的规则并不是十分容易和其他
        部分配合，因为上面出现的 <span class="inlinecode">...</span> 需要被替换为显式的量词（quantification）
        或推导式（comprehension）。基于这个原因，本章最后的扩展练习中并没有包括字段组。
        （这里非形式化地讨论字段组仍然非常有用，因为它为 <a href="Sub.html"><span class="inlineref">Sub</span></a>
        一章中对子类型的讨论提供了基础。）

<div class="paragraph"> </div>


</li>
<li> 此外，我们还可以用一种更简单的方式来表达字段组——比如说，相比与使用单一的构造子
        直接地构造整个字段组，我们可以使用二元的表示，其中一个构造子表示空字段组，
        另一个用于为已有的字段组添加一个新的字段。如果我们主要的兴趣在于学习带字段组
        的演算的元理论，那么这种方式的定义和证明更加简单优雅。在 <a href="Records.html"><span class="inlineref">Records</span></a>
        一章中我们会学习此种处理方式。

<div class="paragraph"> </div>


</li>
<li> 最后，如果我们想的话，也可以通过使用二元组和积类型构造复杂的表达式并模拟字段组
        来完全避免形式化字段组。在下一节中我们简要地描述这种方式。 
</li>
</ul>

</div>

<div class="doc">
<a name="lab257"></a><h3 class="section">编码字段组（选读）</h3>

<div class="paragraph"> </div>

 让我们看看如何只使用二元组和 <span class="inlinecode"><span class="id" type="var">unit</span></span> 来编码字段组。（这种聪明的编码来自于
    Luca Cardelli，基于它也会扩展到具有子类型的系统观察。）

<div class="paragraph"> </div>

    首先，我们可以用嵌套的二元组和 <span class="inlinecode"><span class="id" type="var">unit</span></span> 值来编码任意大小的<b>元组</b>。为了避免重载
    已有的二元组记法 <span class="inlinecode">(<span class="id" type="var">t<sub>1</sub></span>,<span class="id" type="var">t<sub>2</sub></span>)</span>，我们使用无标签的花括号来表示元组，例如 <span class="inlinecode">{}</span>
    是空元组，<span class="inlinecode">{5}</span> 是只有一个元素的元组，<span class="inlinecode">{5,6}</span> 是二元组，
    而 <span class="inlinecode">{5,6,7}</span> 是一个三元组，以此类推。

<div class="paragraph"> </div>

<pre>
      {}                 --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>  unit
      {t<sub>1</sub>, t<sub>2</sub>, ..., tn}  --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>  (t<sub>1</sub>, trest)
                                其中 {t<sub>2</sub>, ..., tn} --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> trest
</pre>
    类似地，我们可以用积类型来表示元组类型：
<pre>
      {}                 --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>  Unit
      {T<sub>1</sub>, T<sub>2</sub>, ..., Tn}  --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>  T<sub>1</sub> * TRest
                                其中 {T<sub>2</sub>, ..., Tn} --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> TRest
</pre>
    从元组中投影出元素的操作可以被编码为连续使用多次（或零次）第二投影操作，
    最后使用第一投影操作：
<pre>
      t.0 --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> t.fst t.(n+1) --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (t.snd).n
</pre>
    下一步，假设在字段组的标签上存在某种全序，那么我们可以为每个标签关联一个唯一的自然数。
    这个数被乘坐标签的<b>位置</b>。比如说，我们可以像下面这样指派位置：
<pre>
      标签     位置
      a       0
      b       1
      c       2
      ...     ...
      bar     1395
      ...     ...
      foo     4460
      ...     ...
</pre>
    我们根据字段的位置对他们排序，并使用这些位置来把字段组编码为元组（也即，嵌套的二元组）。
    例如：
<pre>
      {a=5,b=6} --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> {5,6} {a=5,c=7} --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> {5,unit,7} {c=7,a=5} --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>
      {5,unit,7} {c=5,b=3} --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> {unit,3,5} {f=8,c=5,a=7} --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>
      {7,unit,5,unit,unit,8} {f=8,c=5} --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> {unit,unit,5,unit,unit,8}
</pre>
    请注意，每个字段都出现在他们标签所关联的位置，因此元组的大小取决与有最高位置的标签，
    我们把未使用的位置填充为 <span class="inlinecode"><span class="id" type="var">unit</span></span> 值。

<div class="paragraph"> </div>

    我们在编码字段组类型时使用同样的方式：
<pre>
      {a:Nat,b:Nat} --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> {Nat,Nat} {c:Nat,a:Nat} --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> {Nat,Unit,Nat}
      {f:Nat,c:Nat} --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> {Unit,Unit,Nat,Unit,Unit,Nat}
</pre>
    最后，字段组投影被编码为在正确的位置上对元组投影：
<pre>
      t.l --<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> t.(l 的位置)
</pre>
    我们不难用这种编码来验证以“直接”形式表达的字段组的类型规则。（除了我们编码的是排序后的字段，
    剩下的归约规则几乎已经被验证了。） 
<div class="paragraph"> </div>

 当然，如果我们碰巧使用了标签 <span class="inlinecode"><span class="id" type="var">foo</span></span>，那么这种编码方式并不是十分高效。
    但是这也并没有想象的那样糟糕：比如说，如果假设我们的编译器可以在同一时间获得
    完整的程序，那么我们可以为经常使用的标签<b>选择</b>较小的位置。的确，一些成熟
    的编译器所做的正是如此。
<div class="paragraph"> </div>

<a name="lab258"></a><h3 class="section">变种类型（选读）</h3>

<div class="paragraph"> </div>

 正如同积类型可以泛化为字段组，和类型也可以泛化为 n 元标签类型，称作<b>变种类型（variants）</b>。
    我们可以把其类型写做 <span class="inlinecode">&lt;<span class="id" type="var">l<sub>1</sub></span>:<span class="id" type="var">T<sub>1</sub></span>,<span class="id" type="var">l<sub>2</sub></span>:<span class="id" type="var">T<sub>2</sub></span>,...<span class="id" type="var">ln</span>:<span class="id" type="var">Tn</span>&gt;</span> 而非 <span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span>+<span class="id" type="var">T<sub>2</sub></span></span>，其中 <span class="inlinecode"><span class="id" type="var">l<sub>1</sub></span></span>，<span class="inlinecode"><span class="id" type="var">l<sub>2</sub></span></span>，<span class="inlinecode">...</span>
    是字段的标签，用于构造实例以及解构时分类讨论。

<div class="paragraph"> </div>

    这些 n 元变种类型提供了足够的机制来构造任意的归纳数据类型，比如列表和树。
    唯一缺少的东西是在类型定义中<b>递归（recursion）</b>。在本书中我们不会讲解这些，
    但在许多其他的教材中可以学习到他们，例如 Types and Programming Languages
    一书 <a href="Bib.html#Pierce 2002"><span class="inlineref">[Pierce 2002]</span></a>。
</div>

<div class="doc">
<a name="lab259"></a><h1 class="section">练习：形式化以上扩展</h1>

</div>
<div class="code code-space">

<br/>
<span class="id" type="keyword">Module</span> <span class="id" type="var">STLCExtended</span>.<br/>
</div>

<div class="doc">
<a name="lab260"></a><h4 class="section">练习：3 星, standard (STLCE_definitions)</h4>
 在接下来的一系列练习中，你将会形式化本章中描述的一些扩展。
    我们提供了必要的项和类型的语法，以及一些例子用于测试你的定义是否工作。
    你需要完成剩下的定义，并相应地扩展证明。

<div class="paragraph"> </div>

    作为开始，我们提供了下列实现：

<div class="paragraph"> </div>

<ul class="doclist">
<li> 数值

</li>
<li> 和

</li>
<li> 列表

</li>
<li> 项

</li>
</ul>

<div class="paragraph"> </div>

    你需要完成的实现有：

<div class="paragraph"> </div>

<ul class="doclist">
<li> 二元组

</li>
<li> let（涉及到变量绑定）

</li>
<li> <span class="inlinecode"><span class="id" type="var">fix</span></span>

</li>
</ul>

<div class="paragraph"> </div>

    一个比较好的策略是一次完成一个扩展，分两部完成全部练习，
    而不是尝试一次从头到尾完成本文件中所有的练习。
    对每个定义或证明，首先仔细阅读已经提供的部分，可回顾 <a href="Stlc.html"><span class="inlineref">Stlc</span></a>
    一章中的文本，并展开嵌套的注释复习细节。
</div>

<div class="doc">
<a name="lab261"></a><h3 class="section">语法</h3>

</div>
<div class="code code-space">

<br/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">ty</span> : <span class="id" type="keyword">Type</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">Arrow</span> : <span class="id" type="var">ty</span> → <span class="id" type="var">ty</span> → <span class="id" type="var">ty</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">Nat</span>  : <span class="id" type="var">ty</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">Sum</span>  : <span class="id" type="var">ty</span> → <span class="id" type="var">ty</span> → <span class="id" type="var">ty</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">List</span> : <span class="id" type="var">ty</span> → <span class="id" type="var">ty</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">Unit</span> : <span class="id" type="var">ty</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">Prod</span> : <span class="id" type="var">ty</span> → <span class="id" type="var">ty</span> → <span class="id" type="var">ty</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">tm</span> : <span class="id" type="keyword">Type</span> :=<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;纯&nbsp;STLC&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">var</span> : <span class="id" type="var">string</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">app</span> : <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">abs</span> : <span class="id" type="var">string</span> → <span class="id" type="var">ty</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;数值&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">const</span> : <span class="id" type="var">nat</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">scc</span> : <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">prd</span> : <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">mlt</span> : <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">test0</span>  : <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;和&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">tinl</span> : <span class="id" type="var">ty</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">tinr</span> : <span class="id" type="var">ty</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">tcase</span> : <span class="id" type="var">tm</span> → <span class="id" type="var">string</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">string</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;i.e.,&nbsp;<span class="inlinecode"><span class="id" type="tactic">case</span></span> <span class="inlinecode"><span class="id" type="var">t<sub>0</sub></span></span> <span class="inlinecode"><span class="id" type="var">of</span></span> <span class="inlinecode"><span class="id" type="var">inl</span></span> <span class="inlinecode"><span class="id" type="var">x<sub>1</sub></span></span> <span class="inlinecode">⇒</span> <span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> <span class="inlinecode">|</span> <span class="inlinecode"><span class="id" type="var">inr</span></span> <span class="inlinecode"><span class="id" type="var">x<sub>2</sub></span></span> <span class="inlinecode">⇒</span> <span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span>&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;列表&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">tnil</span> : <span class="id" type="var">ty</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">tcons</span> : <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">tlcase</span> : <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">string</span> → <span class="id" type="var">string</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;i.e.,&nbsp;<span class="inlinecode"><span class="id" type="var">lcase</span></span> <span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> <span class="inlinecode"><span class="id" type="var">of</span></span> <span class="inlinecode">|</span> <span class="inlinecode"><span class="id" type="var">nil</span></span> <span class="inlinecode">⇒</span> <span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span> <span class="inlinecode">|</span> <span class="inlinecode"><span class="id" type="var">x</span>::<span class="id" type="var">y</span></span> <span class="inlinecode">⇒</span> <span class="inlinecode"><span class="id" type="var">t<sub>3</sub></span></span>&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;unit&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">unit</span> : <span class="id" type="var">tm</span><br/>
<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;You&nbsp;are&nbsp;going&nbsp;to&nbsp;be&nbsp;working&nbsp;on&nbsp;the&nbsp;following&nbsp;extensions:&nbsp;*)</span><br/>
<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;pairs&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">pair</span> : <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">fst</span> : <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">snd</span> : <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;let&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">tlet</span> : <span class="id" type="var">string</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;i.e.,&nbsp;<span class="inlinecode"><span class="id" type="keyword">let</span></span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> <span class="inlinecode"><span class="id" type="keyword">in</span></span> <span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span>&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;fix&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">tfix</span>  : <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span>.<br/>
</div>

<div class="doc">
请注意，简洁起见，我们省略了布尔值，但提供了 <span class="inlinecode"><span class="id" type="var">test0</span></span> 用于测试 0 值和作为条件语句。
    也即，当有：
<pre>
       test x = 0 then ... else ...
</pre>
    我们可以写做：
<pre>
       test0 x then ... else ...
</pre>

</div>

<div class="doc">
<a name="lab262"></a><h3 class="section">替换</h3>

</div>
<div class="code code-space">

<br/>
<span class="id" type="keyword">Fixpoint</span> <span class="id" type="tactic">subst</span> (<span class="id" type="var">x</span> : <span class="id" type="var">string</span>) (<span class="id" type="var">s</span> : <span class="id" type="var">tm</span>) (<span class="id" type="var">t</span> : <span class="id" type="var">tm</span>) : <span class="id" type="var">tm</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">t</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;pure&nbsp;STLC&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">var</span> <span class="id" type="var">y</span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">if</span> <span class="id" type="var">eqb_string</span> <span class="id" type="var">x</span> <span class="id" type="var">y</span> <span class="id" type="keyword">then</span> <span class="id" type="var">s</span> <span class="id" type="keyword">else</span> <span class="id" type="var">t</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">abs</span> <span class="id" type="var">y</span> <span class="id" type="var">T</span> <span class="id" type="var">t<sub>1</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">abs</span> <span class="id" type="var">y</span> <span class="id" type="var">T</span> (<span class="id" type="keyword">if</span> <span class="id" type="var">eqb_string</span> <span class="id" type="var">x</span> <span class="id" type="var">y</span> <span class="id" type="keyword">then</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="keyword">else</span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>1</sub></span>))<br/>
&nbsp;&nbsp;| <span class="id" type="var">app</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">app</span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>1</sub></span>) (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;numbers&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">const</span> <span class="id" type="var">n</span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">const</span> <span class="id" type="var">n</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">scc</span> <span class="id" type="var">t<sub>1</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">scc</span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>1</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">prd</span> <span class="id" type="var">t<sub>1</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">prd</span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>1</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">mlt</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">mlt</span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>1</sub></span>) (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">test0</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">test0</span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>1</sub></span>) (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>2</sub></span>) (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>3</sub></span>)<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;sums&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">tinl</span> <span class="id" type="var">T</span> <span class="id" type="var">t<sub>1</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">tinl</span> <span class="id" type="var">T</span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>1</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">tinr</span> <span class="id" type="var">T</span> <span class="id" type="var">t<sub>1</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">tinr</span> <span class="id" type="var">T</span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>1</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">tcase</span> <span class="id" type="var">t<sub>0</sub></span> <span class="id" type="var">y<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">y<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">tcase</span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>0</sub></span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">y<sub>1</sub></span> (<span class="id" type="keyword">if</span> <span class="id" type="var">eqb_string</span> <span class="id" type="var">x</span> <span class="id" type="var">y<sub>1</sub></span> <span class="id" type="keyword">then</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="keyword">else</span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>1</sub></span>))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">y<sub>2</sub></span> (<span class="id" type="keyword">if</span> <span class="id" type="var">eqb_string</span> <span class="id" type="var">x</span> <span class="id" type="var">y<sub>2</sub></span> <span class="id" type="keyword">then</span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="keyword">else</span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>2</sub></span>))<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;lists&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">tnil</span> <span class="id" type="var">T</span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">tnil</span> <span class="id" type="var">T</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">tcons</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">tcons</span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>1</sub></span>) (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">tlcase</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">y<sub>1</sub></span> <span class="id" type="var">y<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">tlcase</span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>1</sub></span>) (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>2</sub></span>) <span class="id" type="var">y<sub>1</sub></span> <span class="id" type="var">y<sub>2</sub></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="keyword">if</span> <span class="id" type="var">eqb_string</span> <span class="id" type="var">x</span> <span class="id" type="var">y<sub>1</sub></span> <span class="id" type="keyword">then</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">t<sub>3</sub></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">else</span> <span class="id" type="keyword">if</span> <span class="id" type="var">eqb_string</span> <span class="id" type="var">x</span> <span class="id" type="var">y<sub>2</sub></span> <span class="id" type="keyword">then</span> <span class="id" type="var">t<sub>3</sub></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">else</span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t<sub>3</sub></span>))<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;unit&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">unit</span> ⇒ <span class="id" type="var">unit</span><br/>
<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;Complete&nbsp;the&nbsp;following&nbsp;cases.&nbsp;*)</span><br/>
<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;pairs&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;let&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;fix&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">_</span> ⇒ <span class="id" type="var">t</span>  <span class="comment">(*&nbsp;...&nbsp;and&nbsp;delete&nbsp;this&nbsp;line&nbsp;when&nbsp;you&nbsp;finish&nbsp;the&nbsp;exercise&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Notation</span> "'[' x ':=' s ']' t" := (<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">s</span> <span class="id" type="var">t</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 20).<br/>
</div>

<div class="doc">
<a name="lab263"></a><h3 class="section">归约</h3>

<div class="paragraph"> </div>

 下面我们定义语言的值。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Inductive</span> <span class="id" type="var">value</span> : <span class="id" type="var">tm</span> → <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;In&nbsp;pure&nbsp;STLC,&nbsp;function&nbsp;abstractions&nbsp;are&nbsp;values:&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">v_abs</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">T<sub>11</sub></span> <span class="id" type="var">t<sub>12</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> (<span class="id" type="var">abs</span> <span class="id" type="var">x</span> <span class="id" type="var">T<sub>11</sub></span> <span class="id" type="var">t<sub>12</sub></span>)<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;数值是值：&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">v_nat</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">n<sub>1</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> (<span class="id" type="var">const</span> <span class="id" type="var">n<sub>1</sub></span>)<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;带标记的值也是值：&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">v_inl</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">v</span> <span class="id" type="var">T</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> <span class="id" type="var">v</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> (<span class="id" type="var">tinl</span> <span class="id" type="var">T</span> <span class="id" type="var">v</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">v_inr</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">v</span> <span class="id" type="var">T</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> <span class="id" type="var">v</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> (<span class="id" type="var">tinr</span> <span class="id" type="var">T</span> <span class="id" type="var">v</span>)<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;列表是值当且仅当其头部（head）和尾部（tail）均为值：*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">v_lnil</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">T</span>, <span class="id" type="var">value</span> (<span class="id" type="var">tnil</span> <span class="id" type="var">T</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">v_lcons</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">vl</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> <span class="id" type="var">v<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> <span class="id" type="var">vl</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> (<span class="id" type="var">tcons</span> <span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">vl</span>)<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;A&nbsp;unit&nbsp;is&nbsp;always&nbsp;a&nbsp;value&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">v_unit</span> : <span class="id" type="var">value</span> <span class="id" type="var">unit</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;A&nbsp;pair&nbsp;is&nbsp;a&nbsp;value&nbsp;if&nbsp;both&nbsp;components&nbsp;are:&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">v_pair</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">v<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> <span class="id" type="var">v<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> <span class="id" type="var">v<sub>2</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> (<span class="id" type="var">pair</span> <span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">v<sub>2</sub></span>).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Hint</span> <span class="id" type="var">Constructors</span> <span class="id" type="var">value</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Reserved Notation</span> "t<sub>1</sub> '<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>' t<sub>2</sub>" (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 40).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">step</span> : <span class="id" type="var">tm</span> → <span class="id" type="var">tm</span> → <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;pure&nbsp;STLC&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_AppAbs</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">T<sub>11</sub></span> <span class="id" type="var">t<sub>12</sub></span> <span class="id" type="var">v<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> <span class="id" type="var">v<sub>2</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">app</span> (<span class="id" type="var">abs</span> <span class="id" type="var">x</span> <span class="id" type="var">T<sub>11</sub></span> <span class="id" type="var">t<sub>12</sub></span>) <span class="id" type="var">v<sub>2</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> [<span class="id" type="var">x</span>:=<span class="id" type="var">v<sub>2</sub></span>]<span class="id" type="var">t<sub>12</sub></span><br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_App1</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">t<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">t<sub>1</sub></span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>1</sub>'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">app</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">app</span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_App2</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub>'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> <span class="id" type="var">v<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">t<sub>2</sub></span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>2</sub>'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">app</span> <span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">app</span> <span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub>'</span>)<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;数值&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_Succ1</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub>'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">t<sub>1</sub></span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>1</sub>'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">scc</span> <span class="id" type="var">t<sub>1</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">scc</span> <span class="id" type="var">t<sub>1</sub>'</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_SuccNat</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">n<sub>1</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">scc</span> (<span class="id" type="var">const</span> <span class="id" type="var">n<sub>1</sub></span>)) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">const</span> (<span class="id" type="var">S</span> <span class="id" type="var">n<sub>1</sub></span>))<br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_Pred</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub>'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">t<sub>1</sub></span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>1</sub>'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">prd</span> <span class="id" type="var">t<sub>1</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">prd</span> <span class="id" type="var">t<sub>1</sub>'</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_PredNat</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">n<sub>1</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">prd</span> (<span class="id" type="var">const</span> <span class="id" type="var">n<sub>1</sub></span>)) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">const</span> (<span class="id" type="var">pred</span> <span class="id" type="var">n<sub>1</sub></span>))<br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_Mult1</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">t<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">t<sub>1</sub></span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>1</sub>'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">mlt</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">mlt</span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_Mult2</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub>'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> <span class="id" type="var">v<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">t<sub>2</sub></span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>2</sub>'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">mlt</span> <span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">mlt</span> <span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub>'</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_Mulconsts</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">n<sub>1</sub></span> <span class="id" type="var">n<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">mlt</span> (<span class="id" type="var">const</span> <span class="id" type="var">n<sub>1</sub></span>) (<span class="id" type="var">const</span> <span class="id" type="var">n<sub>2</sub></span>)) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">const</span> (<span class="id" type="var">mult</span> <span class="id" type="var">n<sub>1</sub></span> <span class="id" type="var">n<sub>2</sub></span>))<br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_Test01</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">t<sub>1</sub></span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>1</sub>'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">test0</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">test0</span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_Test0Zero</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">test0</span> (<span class="id" type="var">const</span> 0) <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>2</sub></span><br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_Test0Nonzero</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">n</span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">test0</span> (<span class="id" type="var">const</span> (<span class="id" type="var">S</span> <span class="id" type="var">n</span>)) <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>3</sub></span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;sums&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_Inl</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">T</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">t<sub>1</sub></span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>1</sub>'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tinl</span> <span class="id" type="var">T</span> <span class="id" type="var">t<sub>1</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">tinl</span> <span class="id" type="var">T</span> <span class="id" type="var">t<sub>1</sub>'</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_Inr</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">T</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">t<sub>1</sub></span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>1</sub>'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tinr</span> <span class="id" type="var">T</span> <span class="id" type="var">t<sub>1</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">tinr</span> <span class="id" type="var">T</span> <span class="id" type="var">t<sub>1</sub>'</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_Case</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">t<sub>0</sub></span> <span class="id" type="var">t<sub>0</sub>'</span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">t<sub>0</sub></span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>0</sub>'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tcase</span> <span class="id" type="var">t<sub>0</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">tcase</span> <span class="id" type="var">t<sub>0</sub>'</span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_CaseInl</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">v<sub>0</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">T</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> <span class="id" type="var">v<sub>0</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tcase</span> (<span class="id" type="var">tinl</span> <span class="id" type="var">T</span> <span class="id" type="var">v<sub>0</sub></span>) <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> [<span class="id" type="var">x<sub>1</sub></span>:=<span class="id" type="var">v<sub>0</sub></span>]<span class="id" type="var">t<sub>1</sub></span><br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_CaseInr</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">v<sub>0</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">T</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> <span class="id" type="var">v<sub>0</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tcase</span> (<span class="id" type="var">tinr</span> <span class="id" type="var">T</span> <span class="id" type="var">v<sub>0</sub></span>) <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> [<span class="id" type="var">x<sub>2</sub></span>:=<span class="id" type="var">v<sub>0</sub></span>]<span class="id" type="var">t<sub>2</sub></span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;lists&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_Cons1</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">t<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">t<sub>1</sub></span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>1</sub>'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tcons</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">tcons</span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_Cons2</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub>'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> <span class="id" type="var">v<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">t<sub>2</sub></span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>2</sub>'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tcons</span> <span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">tcons</span> <span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub>'</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_Lcase1</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">t<sub>1</sub></span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>1</sub>'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tlcase</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="var">tlcase</span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_LcaseNil</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">T</span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tlcase</span> (<span class="id" type="var">tnil</span> <span class="id" type="var">T</span>) <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t<sub>2</sub></span><br/>
&nbsp;&nbsp;| <span class="id" type="var">ST_LcaseCons</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">vl</span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> <span class="id" type="var">v<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> <span class="id" type="var">vl</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tlcase</span> (<span class="id" type="var">tcons</span> <span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">vl</span>) <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">vl</span> (<span class="id" type="tactic">subst</span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">v<sub>1</sub></span> <span class="id" type="var">t<sub>3</sub></span>))<br/>
<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;Add&nbsp;rules&nbsp;for&nbsp;the&nbsp;following&nbsp;extensions.&nbsp;*)</span><br/>
<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;二元组&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;let&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;fix&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
<br/>
<span class="id" type="keyword">where</span> "t<sub>1</sub> '<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>' t<sub>2</sub>" := (<span class="id" type="var">step</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">multistep</span> := (<span class="id" type="var">multi</span> <span class="id" type="var">step</span>).<br/>
<span class="id" type="keyword">Notation</span> "t<sub>1</sub> '<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>&gt;</span><span style='vertical-align:15%;'>*</span></span></span>' t<sub>2</sub>" := (<span class="id" type="var">multistep</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 40).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Hint</span> <span class="id" type="var">Constructors</span> <span class="id" type="var">step</span>.<br/>
</div>

<div class="doc">
<a name="lab264"></a><h3 class="section">定型</h3>

</div>
<div class="code code-space">

<br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">context</span> := <span class="id" type="var">partial_map</span> <span class="id" type="var">ty</span>.<br/>
</div>

<div class="doc">
下面我们定义类型规则，这基本上是直接将推断规则翻译一下。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Reserved Notation</span> "Gamma '&#x22A2;' t '&#x2208;' T" (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 40).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">has_type</span> : <span class="id" type="var">context</span> → <span class="id" type="var">tm</span> → <span class="id" type="var">ty</span> → <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;纯&nbsp;STLC&nbsp;的定型规则&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">T_Var</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span> <span class="id" type="var">x</span> <span class="id" type="var">T</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> <span class="id" type="var">x</span> = <span class="id" type="var">Some</span> <span class="id" type="var">T</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; (<span class="id" type="var">var</span> <span class="id" type="var">x</span>) &#x2208; <span class="id" type="var">T</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">T_Abs</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span> <span class="id" type="var">x</span> <span class="id" type="var">T<sub>11</sub></span> <span class="id" type="var">T<sub>12</sub></span> <span class="id" type="var">t<sub>12</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">update</span> <span class="id" type="var">Gamma</span> <span class="id" type="var">x</span> <span class="id" type="var">T<sub>11</sub></span>) &#x22A2; <span class="id" type="var">t<sub>12</sub></span> &#x2208; <span class="id" type="var">T<sub>12</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; (<span class="id" type="var">abs</span> <span class="id" type="var">x</span> <span class="id" type="var">T<sub>11</sub></span> <span class="id" type="var">t<sub>12</sub></span>) &#x2208; (<span class="id" type="var">Arrow</span> <span class="id" type="var">T<sub>11</sub></span> <span class="id" type="var">T<sub>12</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">T_App</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">T<sub>1</sub></span> <span class="id" type="var">T<sub>2</sub></span> <span class="id" type="var">Gamma</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>1</sub></span> &#x2208; (<span class="id" type="var">Arrow</span> <span class="id" type="var">T<sub>1</sub></span> <span class="id" type="var">T<sub>2</sub></span>) →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>2</sub></span> &#x2208; <span class="id" type="var">T<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; (<span class="id" type="var">app</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>) &#x2208; <span class="id" type="var">T<sub>2</sub></span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;数值&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">T_Nat</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span> <span class="id" type="var">n<sub>1</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; (<span class="id" type="var">const</span> <span class="id" type="var">n<sub>1</sub></span>) &#x2208; <span class="id" type="var">Nat</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">T_Succ</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span> <span class="id" type="var">t<sub>1</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>1</sub></span> &#x2208; <span class="id" type="var">Nat</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; (<span class="id" type="var">scc</span> <span class="id" type="var">t<sub>1</sub></span>) &#x2208; <span class="id" type="var">Nat</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">T_Pred</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span> <span class="id" type="var">t<sub>1</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>1</sub></span> &#x2208; <span class="id" type="var">Nat</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; (<span class="id" type="var">prd</span> <span class="id" type="var">t<sub>1</sub></span>) &#x2208; <span class="id" type="var">Nat</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">T_Mult</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>1</sub></span> &#x2208; <span class="id" type="var">Nat</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>2</sub></span> &#x2208; <span class="id" type="var">Nat</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; (<span class="id" type="var">mlt</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>) &#x2208; <span class="id" type="var">Nat</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">T_Test0</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span> <span class="id" type="var">T<sub>1</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>1</sub></span> &#x2208; <span class="id" type="var">Nat</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>2</sub></span> &#x2208; <span class="id" type="var">T<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>3</sub></span> &#x2208; <span class="id" type="var">T<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; (<span class="id" type="var">test0</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>) &#x2208; <span class="id" type="var">T<sub>1</sub></span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;和&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">T_Inl</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">T<sub>1</sub></span> <span class="id" type="var">T<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>1</sub></span> &#x2208; <span class="id" type="var">T<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; (<span class="id" type="var">tinl</span> <span class="id" type="var">T<sub>2</sub></span> <span class="id" type="var">t<sub>1</sub></span>) &#x2208; (<span class="id" type="var">Sum</span> <span class="id" type="var">T<sub>1</sub></span> <span class="id" type="var">T<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">T_Inr</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">T<sub>1</sub></span> <span class="id" type="var">T<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>2</sub></span> &#x2208; <span class="id" type="var">T<sub>2</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; (<span class="id" type="var">tinr</span> <span class="id" type="var">T<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>) &#x2208; (<span class="id" type="var">Sum</span> <span class="id" type="var">T<sub>1</sub></span> <span class="id" type="var">T<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">T_Case</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span> <span class="id" type="var">t<sub>0</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">T<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">T<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">T</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>0</sub></span> &#x2208; (<span class="id" type="var">Sum</span> <span class="id" type="var">T<sub>1</sub></span> <span class="id" type="var">T<sub>2</sub></span>) →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">update</span> <span class="id" type="var">Gamma</span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">T<sub>1</sub></span>) &#x22A2; <span class="id" type="var">t<sub>1</sub></span> &#x2208; <span class="id" type="var">T</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">update</span> <span class="id" type="var">Gamma</span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">T<sub>2</sub></span>) &#x22A2; <span class="id" type="var">t<sub>2</sub></span> &#x2208; <span class="id" type="var">T</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; (<span class="id" type="var">tcase</span> <span class="id" type="var">t<sub>0</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span>) &#x2208; <span class="id" type="var">T</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;列表&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">T_Nil</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span> <span class="id" type="var">T</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; (<span class="id" type="var">tnil</span> <span class="id" type="var">T</span>) &#x2208; (<span class="id" type="var">List</span> <span class="id" type="var">T</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">T_Cons</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">T<sub>1</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>1</sub></span> &#x2208; <span class="id" type="var">T<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>2</sub></span> &#x2208; (<span class="id" type="var">List</span> <span class="id" type="var">T<sub>1</sub></span>) →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; (<span class="id" type="var">tcons</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>) &#x2208; (<span class="id" type="var">List</span> <span class="id" type="var">T<sub>1</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">T_Lcase</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">T<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span> <span class="id" type="var">T<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>1</sub></span> &#x2208; (<span class="id" type="var">List</span> <span class="id" type="var">T<sub>1</sub></span>) →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t<sub>2</sub></span> &#x2208; <span class="id" type="var">T<sub>2</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">update</span> (<span class="id" type="var">update</span> <span class="id" type="var">Gamma</span> <span class="id" type="var">x<sub>2</sub></span> (<span class="id" type="var">List</span> <span class="id" type="var">T<sub>1</sub></span>)) <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">T<sub>1</sub></span>) &#x22A2; <span class="id" type="var">t<sub>3</sub></span> &#x2208; <span class="id" type="var">T<sub>2</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; (<span class="id" type="var">tlcase</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>) &#x2208; <span class="id" type="var">T<sub>2</sub></span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;unit&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">T_Unit</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">unit</span> &#x2208; <span class="id" type="var">Unit</span><br/>
<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;Add&nbsp;rules&nbsp;for&nbsp;the&nbsp;following&nbsp;extensions.&nbsp;*)</span><br/>
<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;pairs&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;let&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;fix&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
<br/>
<span class="id" type="keyword">where</span> "Gamma '&#x22A2;' t '&#x2208;' T" := (<span class="id" type="var">has_type</span> <span class="id" type="var">Gamma</span> <span class="id" type="var">t</span> <span class="id" type="var">T</span>).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Hint</span> <span class="id" type="var">Constructors</span> <span class="id" type="var">has_type</span>.<br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;请勿修改下面这一行：&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">manual_grade_for_extensions_definition</span> : <span class="id" type="var">option</span> (<span class="id" type="var">nat</span>*<span class="id" type="var">string</span>) := <span class="id" type="var">None</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 

<div class="doc">
<a name="lab265"></a><h2 class="section">例子</h2>

<div class="paragraph"> </div>

<a name="lab266"></a><h4 class="section">练习：3 星, standard (STLCE_examples)</h4>
 本节形式化了一些上文中出现的例子（以及一些其他的例子）。

<div class="paragraph"> </div>

    只要你为通过测试实现了足够的定义，就取消证明的注释并将 <span class="inlinecode"><span class="id" type="var">Admitted</span></span> 替换为 <span class="inlinecode"><span class="id" type="keyword">Qed</span></span>。

<div class="paragraph"> </div>

    最开始我们会专注于某些特性，而在开始证明这些特性之前，你可以用一些例子先来
    测试一下你的定义是否合理。后面的例子会整合全部的特性，因此你需要在完成所有的
    定义后再阅读这部分。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Module</span> <span class="id" type="var">Examples</span>.<br/>
</div>

<div class="doc">
<a name="lab267"></a><h3 class="section">基础</h3>

<div class="paragraph"> </div>

 首先，让我们定义几个变量： 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Open</span> <span class="id" type="keyword">Scope</span> <span class="id" type="var">string_scope</span>.<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">x</span> := "x".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">y</span> := "y".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">a</span> := "a".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">f</span> := "f".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">g</span> := "g".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">l</span> := "l".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">k</span> := "k".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">i<sub>1</sub></span> := "i<sub>1</sub>".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">i<sub>2</sub></span> := "i<sub>2</sub>".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">processSum</span> := "processSum".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">n</span> := "n".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">eq</span> := "eq".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">m</span> := "m".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">evenodd</span> := "evenodd".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">even</span> := "even".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">odd</span> := "odd".<br/>
<span class="id" type="keyword">Notation</span> <span class="id" type="var">eo</span> := "eo".<br/>
</div>

<div class="doc">
下面，我们为 Coq 提供一些提示来自动地搜索类型导出式。你不需要理解这部分的全部细节——
    大概看一下便可，当你需要自己扩展 <span class="inlinecode"><span class="id" type="tactic">auto</span></span> 时可再回过头来学习。

<div class="paragraph"> </div>

    下面的 <span class="inlinecode"><span class="id" type="keyword">Hint</span></span> 定义是说，当 <span class="inlinecode"><span class="id" type="tactic">auto</span></span> 遇到一个形如 <span class="inlinecode">(<span class="id" type="var">Gamma</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode">(<span class="id" type="var">app</span></span> <span class="inlinecode"><span class="id" type="var">e<sub>1</sub></span></span> <span class="inlinecode"><span class="id" type="var">e<sub>1</sub></span>)</span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">T</span>)</span>
    的目标时，它应当考虑使用 <span class="inlinecode"><span class="id" type="tactic">eapply</span></span> <span class="inlinecode"><span class="id" type="var">T_App</span></span>，并为中间的类型 T<sub>1</sub> 留下一个存在变量。
    <span class="inlinecode"><span class="id" type="var">lcase</span></span> 与此类似。这个变量在后面为 <span class="inlinecode"><span class="id" type="var">e<sub>1</sub></span></span> 和 <span class="inlinecode"><span class="id" type="var">e<sub>2</sub></span></span> 搜索类型导出式的过程中会被填补。
    我们还引入一个提示用于搜索形如等式的证明目标；这对使用 <span class="inlinecode"><span class="id" type="var">T_Var</span></span> 的情景非常有用
    （其含有一个等式作为前提条件）。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Hint</span> <span class="id" type="keyword">Extern</span> 2 (<span class="id" type="var">has_type</span> <span class="id" type="var">_</span> (<span class="id" type="var">app</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span>) <span class="id" type="var">_</span>) ⇒<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">T_App</span>; <span class="id" type="tactic">auto</span>.<br/>
<span class="id" type="keyword">Hint</span> <span class="id" type="keyword">Extern</span> 2 (<span class="id" type="var">has_type</span> <span class="id" type="var">_</span> (<span class="id" type="var">tlcase</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span>) <span class="id" type="var">_</span>) ⇒<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">T_Lcase</span>; <span class="id" type="tactic">auto</span>.<br/>
<span class="id" type="keyword">Hint</span> <span class="id" type="keyword">Extern</span> 2 (<span class="id" type="var">_</span> = <span class="id" type="var">_</span>) ⇒ <span class="id" type="tactic">compute</span>; <span class="id" type="tactic">reflexivity</span>.<br/>
</div>

<div class="doc">
<a name="lab268"></a><h3 class="section">数值</h3>

</div>
<div class="code code-space">

<br/>
<span class="id" type="keyword">Module</span> <span class="id" type="var">Numtest</span>.<br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;test0&nbsp;(pred&nbsp;(succ&nbsp;(pred&nbsp;(2&nbsp;*&nbsp;0)))&nbsp;then&nbsp;5&nbsp;else&nbsp;6&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">test</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="var">test0</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">prd</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">scc</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">prd</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">mlt</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">const</span> 2)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">const</span> 0)))))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">const</span> 5)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">const</span> 6).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">typechecks</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">empty</span> &#x22A2; <span class="id" type="var">test</span> &#x2208; <span class="id" type="var">Nat</span>.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">test</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;这里的类型导出式非常深，因此我们需要将&nbsp;<span class="inlinecode"><span class="id" type="tactic">auto</span></span>&nbsp;的最大搜索深度从&nbsp;5&nbsp;改为&nbsp;10。&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="id" type="tactic">auto</span> 10.<br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">numtest_reduces</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">test</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>&gt;</span><span style='vertical-align:15%;'>*</span></span></span> <span class="id" type="var">const</span> 5.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
<span class="comment">(*&nbsp;<br/>
&nbsp;&nbsp;unfold&nbsp;test.&nbsp;normalize.<br/>
*)</span><br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">End</span> <span class="id" type="var">Numtest</span>.<br/>
</div>

<div class="doc">
<a name="lab269"></a><h3 class="section">积</h3>

</div>
<div class="code code-space">

<br/>
<span class="id" type="keyword">Module</span> <span class="id" type="var">Prodtest</span>.<br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;((5,6),7).fst.snd&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">test</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="var">snd</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">fst</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">pair</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">pair</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">const</span> 5)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">const</span> 6))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">const</span> 7))).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">typechecks</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">empty</span> &#x22A2; <span class="id" type="var">test</span> &#x2208; <span class="id" type="var">Nat</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">test</span>. <span class="id" type="tactic">eauto</span> 15. <span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
<span class="comment">(*&nbsp;GRADE_THEOREM&nbsp;0.25:&nbsp;typechecks&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">reduces</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">test</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>&gt;</span><span style='vertical-align:15%;'>*</span></span></span> <span class="id" type="var">const</span> 6.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
<span class="comment">(*&nbsp;<br/>
&nbsp;&nbsp;unfold&nbsp;test.&nbsp;normalize.<br/>
*)</span><br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
<span class="comment">(*&nbsp;GRADE_THEOREM&nbsp;0.25:&nbsp;reduces&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">End</span> <span class="id" type="var">Prodtest</span>.<br/>
</div>

<div class="doc">
<a name="lab270"></a><h3 class="section"><span class="inlinecode"><span class="id" type="keyword">let</span></span></h3>

</div>
<div class="code code-space">

<br/>
<span class="id" type="keyword">Module</span> <span class="id" type="var">LetTest</span>.<br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;let&nbsp;x&nbsp;=&nbsp;pred&nbsp;6&nbsp;in&nbsp;succ&nbsp;x&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">test</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="var">tlet</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">x</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">prd</span> (<span class="id" type="var">const</span> 6))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">scc</span> (<span class="id" type="var">var</span> <span class="id" type="var">x</span>)).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">typechecks</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">empty</span> &#x22A2; <span class="id" type="var">test</span> &#x2208; <span class="id" type="var">Nat</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">test</span>. <span class="id" type="tactic">eauto</span> 15. <span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
<span class="comment">(*&nbsp;GRADE_THEOREM&nbsp;0.25:&nbsp;typechecks&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">reduces</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">test</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>&gt;</span><span style='vertical-align:15%;'>*</span></span></span> <span class="id" type="var">const</span> 6.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
<span class="comment">(*&nbsp;<br/>
&nbsp;&nbsp;unfold&nbsp;test.&nbsp;normalize.<br/>
*)</span><br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
<span class="comment">(*&nbsp;GRADE_THEOREM&nbsp;0.25:&nbsp;reduces&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">End</span> <span class="id" type="var">LetTest</span>.<br/>
</div>

<div class="doc">
<a name="lab271"></a><h3 class="section">和</h3>

</div>
<div class="code code-space">

<br/>
<span class="id" type="keyword">Module</span> <span class="id" type="var">Sumtest1</span>.<br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;case&nbsp;(inl&nbsp;Nat&nbsp;5)&nbsp;of<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inl&nbsp;x&nbsp;=&gt;&nbsp;x<br/>
&nbsp;&nbsp;&nbsp;|&nbsp;inr&nbsp;y&nbsp;=&gt;&nbsp;y&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">test</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="var">tcase</span> (<span class="id" type="var">tinl</span> <span class="id" type="var">Nat</span> (<span class="id" type="var">const</span> 5))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">x</span> (<span class="id" type="var">var</span> <span class="id" type="var">x</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">y</span> (<span class="id" type="var">var</span> <span class="id" type="var">y</span>).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">typechecks</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">empty</span> &#x22A2; <span class="id" type="var">test</span> &#x2208; <span class="id" type="var">Nat</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">test</span>. <span class="id" type="tactic">eauto</span> 15. <span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">reduces</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">test</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>&gt;</span><span style='vertical-align:15%;'>*</span></span></span> (<span class="id" type="var">const</span> 5).<br/>
<span class="id" type="keyword">Proof</span>.<br/>
<span class="comment">(*&nbsp;<br/>
&nbsp;&nbsp;unfold&nbsp;test.&nbsp;normalize.<br/>
*)</span><br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">End</span> <span class="id" type="var">Sumtest1</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Module</span> <span class="id" type="var">Sumtest2</span>.<br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;let&nbsp;processSum&nbsp;=<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\x:Nat+Nat.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;x&nbsp;of<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inl&nbsp;n&nbsp;=&gt;&nbsp;n<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inr&nbsp;n&nbsp;=&gt;&nbsp;test0&nbsp;n&nbsp;then&nbsp;1&nbsp;else&nbsp;0&nbsp;in<br/>
&nbsp;&nbsp;&nbsp;(processSum&nbsp;(inl&nbsp;Nat&nbsp;5),&nbsp;processSum&nbsp;(inr&nbsp;Nat&nbsp;5))&nbsp;&nbsp;&nbsp;&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">test</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="var">tlet</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">processSum</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">abs</span> <span class="id" type="var">x</span> (<span class="id" type="var">Sum</span> <span class="id" type="var">Nat</span> <span class="id" type="var">Nat</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tcase</span> (<span class="id" type="var">var</span> <span class="id" type="var">x</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">n</span> (<span class="id" type="var">var</span> <span class="id" type="var">n</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">n</span> (<span class="id" type="var">test0</span> (<span class="id" type="var">var</span> <span class="id" type="var">n</span>) (<span class="id" type="var">const</span> 1) (<span class="id" type="var">const</span> 0))))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">pair</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">app</span> (<span class="id" type="var">var</span> <span class="id" type="var">processSum</span>) (<span class="id" type="var">tinl</span> <span class="id" type="var">Nat</span> (<span class="id" type="var">const</span> 5)))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">app</span> (<span class="id" type="var">var</span> <span class="id" type="var">processSum</span>) (<span class="id" type="var">tinr</span> <span class="id" type="var">Nat</span> (<span class="id" type="var">const</span> 5)))).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">typechecks</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">empty</span> &#x22A2; <span class="id" type="var">test</span> &#x2208; (<span class="id" type="var">Prod</span> <span class="id" type="var">Nat</span> <span class="id" type="var">Nat</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">test</span>. <span class="id" type="tactic">eauto</span> 15. <span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">reduces</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">test</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>&gt;</span><span style='vertical-align:15%;'>*</span></span></span> (<span class="id" type="var">pair</span> (<span class="id" type="var">const</span> 5) (<span class="id" type="var">const</span> 0)).<br/>
<span class="id" type="keyword">Proof</span>.<br/>
<span class="comment">(*&nbsp;<br/>
&nbsp;&nbsp;unfold&nbsp;test.&nbsp;normalize.<br/>
*)</span><br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">End</span> <span class="id" type="var">Sumtest2</span>.<br/>
</div>

<div class="doc">
<a name="lab272"></a><h3 class="section">列表</h3>

</div>
<div class="code code-space">

<br/>
<span class="id" type="keyword">Module</span> <span class="id" type="var">ListTest</span>.<br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;let&nbsp;l&nbsp;=&nbsp;cons&nbsp;5&nbsp;(cons&nbsp;6&nbsp;(nil&nbsp;Nat))&nbsp;in<br/>
&nbsp;&nbsp;&nbsp;lcase&nbsp;l&nbsp;of<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nil&nbsp;=&gt;&nbsp;0<br/>
&nbsp;&nbsp;&nbsp;|&nbsp;x::y&nbsp;=&gt;&nbsp;x*x&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">test</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="var">tlet</span> <span class="id" type="var">l</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tcons</span> (<span class="id" type="var">const</span> 5) (<span class="id" type="var">tcons</span> (<span class="id" type="var">const</span> 6) (<span class="id" type="var">tnil</span> <span class="id" type="var">Nat</span>)))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tlcase</span> (<span class="id" type="var">var</span> <span class="id" type="var">l</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">const</span> 0)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">x</span> <span class="id" type="var">y</span> (<span class="id" type="var">mlt</span> (<span class="id" type="var">var</span> <span class="id" type="var">x</span>) (<span class="id" type="var">var</span> <span class="id" type="var">x</span>))).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">typechecks</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">empty</span> &#x22A2; <span class="id" type="var">test</span> &#x2208; <span class="id" type="var">Nat</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">test</span>. <span class="id" type="tactic">eauto</span> 20. <span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">reduces</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">test</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>&gt;</span><span style='vertical-align:15%;'>*</span></span></span> (<span class="id" type="var">const</span> 25).<br/>
<span class="id" type="keyword">Proof</span>.<br/>
<span class="comment">(*&nbsp;<br/>
&nbsp;&nbsp;unfold&nbsp;test.&nbsp;normalize.<br/>
*)</span><br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">End</span> <span class="id" type="var">ListTest</span>.<br/>
</div>

<div class="doc">
<a name="lab273"></a><h3 class="section"><span class="inlinecode"><span class="id" type="var">fix</span></span></h3>

</div>
<div class="code code-space">

<br/>
<span class="id" type="keyword">Module</span> <span class="id" type="var">FixTest1</span>.<br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;fact&nbsp;:=&nbsp;fix<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(\f:nat<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>nat.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\a:nat.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;test&nbsp;a=0&nbsp;then&nbsp;1&nbsp;else&nbsp;a&nbsp;*&nbsp;(f&nbsp;(pred&nbsp;a)))&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">fact</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="var">tfix</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">abs</span> <span class="id" type="var">f</span> (<span class="id" type="var">Arrow</span> <span class="id" type="var">Nat</span> <span class="id" type="var">Nat</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">abs</span> <span class="id" type="var">a</span> <span class="id" type="var">Nat</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">test0</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">var</span> <span class="id" type="var">a</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">const</span> 1)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">mlt</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">var</span> <span class="id" type="var">a</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">app</span> (<span class="id" type="var">var</span> <span class="id" type="var">f</span>) (<span class="id" type="var">prd</span> (<span class="id" type="var">var</span> <span class="id" type="var">a</span>))))))).<br/>
</div>

<div class="doc">
（警告：<span class="inlinecode"><span class="id" type="var">fact</span></span> 可能通过了类型检查但仍然会有一些类型规则是错误的！） 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Example</span> <span class="id" type="var">typechecks</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">empty</span> &#x22A2; <span class="id" type="var">fact</span> &#x2208; (<span class="id" type="var">Arrow</span> <span class="id" type="var">Nat</span> <span class="id" type="var">Nat</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">fact</span>. <span class="id" type="tactic">auto</span> 10. <span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
<span class="comment">(*&nbsp;GRADE_THEOREM&nbsp;0.25:&nbsp;typechecks&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">reduces</span> :<br/>
&nbsp;&nbsp;(<span class="id" type="var">app</span> <span class="id" type="var">fact</span> (<span class="id" type="var">const</span> 4)) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>&gt;</span><span style='vertical-align:15%;'>*</span></span></span> (<span class="id" type="var">const</span> 24).<br/>
<span class="id" type="keyword">Proof</span>.<br/>
<span class="comment">(*&nbsp;<br/>
&nbsp;&nbsp;unfold&nbsp;fact.&nbsp;normalize.<br/>
*)</span><br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
<span class="comment">(*&nbsp;GRADE_THEOREM&nbsp;0.25:&nbsp;reduces&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">End</span> <span class="id" type="var">FixTest1</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Module</span> <span class="id" type="var">FixTest2</span>.<br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;map&nbsp;:=<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\g:nat<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>nat.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fix<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(\f:<span class="inlinecode"><span class="id" type="var">nat</span></span><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span><span class="inlinecode"><span class="id" type="var">nat</span></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\l:<span class="inlinecode"><span class="id" type="var">nat</span></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;l&nbsp;of<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;<span class="inlinecode"></span>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;<span class="inlinecode"></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;x::l&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;(g&nbsp;x)::(f&nbsp;l))&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">map</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="var">abs</span> <span class="id" type="var">g</span> (<span class="id" type="var">Arrow</span> <span class="id" type="var">Nat</span> <span class="id" type="var">Nat</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tfix</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">abs</span> <span class="id" type="var">f</span> (<span class="id" type="var">Arrow</span> (<span class="id" type="var">List</span> <span class="id" type="var">Nat</span>) (<span class="id" type="var">List</span> <span class="id" type="var">Nat</span>))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">abs</span> <span class="id" type="var">l</span> (<span class="id" type="var">List</span> <span class="id" type="var">Nat</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tlcase</span> (<span class="id" type="var">var</span> <span class="id" type="var">l</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tnil</span> <span class="id" type="var">Nat</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">a</span> <span class="id" type="var">l</span> (<span class="id" type="var">tcons</span> (<span class="id" type="var">app</span> (<span class="id" type="var">var</span> <span class="id" type="var">g</span>) (<span class="id" type="var">var</span> <span class="id" type="var">a</span>))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">app</span> (<span class="id" type="var">var</span> <span class="id" type="var">f</span>) (<span class="id" type="var">var</span> <span class="id" type="var">l</span>))))))).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">typechecks</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">empty</span> &#x22A2; <span class="id" type="var">map</span> &#x2208;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">Arrow</span> (<span class="id" type="var">Arrow</span> <span class="id" type="var">Nat</span> <span class="id" type="var">Nat</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">Arrow</span> (<span class="id" type="var">List</span> <span class="id" type="var">Nat</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">List</span> <span class="id" type="var">Nat</span>))).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">map</span>. <span class="id" type="tactic">auto</span> 10. <span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
<span class="comment">(*&nbsp;GRADE_THEOREM&nbsp;0.25:&nbsp;typechecks&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">reduces</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">app</span> (<span class="id" type="var">app</span> <span class="id" type="var">map</span> (<span class="id" type="var">abs</span> <span class="id" type="var">a</span> <span class="id" type="var">Nat</span> (<span class="id" type="var">scc</span> (<span class="id" type="var">var</span> <span class="id" type="var">a</span>))))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tcons</span> (<span class="id" type="var">const</span> 1) (<span class="id" type="var">tcons</span> (<span class="id" type="var">const</span> 2) (<span class="id" type="var">tnil</span> <span class="id" type="var">Nat</span>)))<br/>
&nbsp;&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>&gt;</span><span style='vertical-align:15%;'>*</span></span></span> (<span class="id" type="var">tcons</span> (<span class="id" type="var">const</span> 2) (<span class="id" type="var">tcons</span> (<span class="id" type="var">const</span> 3) (<span class="id" type="var">tnil</span> <span class="id" type="var">Nat</span>))).<br/>
<span class="id" type="keyword">Proof</span>.<br/>
<span class="comment">(*&nbsp;<br/>
&nbsp;&nbsp;unfold&nbsp;map.&nbsp;normalize.<br/>
*)</span><br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
<span class="comment">(*&nbsp;GRADE_THEOREM&nbsp;0.25:&nbsp;reduces&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">End</span> <span class="id" type="var">FixTest2</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Module</span> <span class="id" type="var">FixTest3</span>.<br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;equal&nbsp;=<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fix<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(\eq:Nat<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>Nat<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>Bool.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\m:Nat.&nbsp;\n:Nat.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;test0&nbsp;m&nbsp;then&nbsp;(test0&nbsp;n&nbsp;then&nbsp;1&nbsp;else&nbsp;0)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;test0&nbsp;n&nbsp;then&nbsp;0<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;eq&nbsp;(pred&nbsp;m)&nbsp;(pred&nbsp;n))&nbsp;&nbsp;&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">equal</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="var">tfix</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">abs</span> <span class="id" type="var">eq</span> (<span class="id" type="var">Arrow</span> <span class="id" type="var">Nat</span> (<span class="id" type="var">Arrow</span> <span class="id" type="var">Nat</span> <span class="id" type="var">Nat</span>))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">abs</span> <span class="id" type="var">m</span> <span class="id" type="var">Nat</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">abs</span> <span class="id" type="var">n</span> <span class="id" type="var">Nat</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">test0</span> (<span class="id" type="var">var</span> <span class="id" type="var">m</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">test0</span> (<span class="id" type="var">var</span> <span class="id" type="var">n</span>) (<span class="id" type="var">const</span> 1) (<span class="id" type="var">const</span> 0))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">test0</span> (<span class="id" type="var">var</span> <span class="id" type="var">n</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">const</span> 0)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">app</span> (<span class="id" type="var">app</span> (<span class="id" type="var">var</span> <span class="id" type="var">eq</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">prd</span> (<span class="id" type="var">var</span> <span class="id" type="var">m</span>)))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">prd</span> (<span class="id" type="var">var</span> <span class="id" type="var">n</span>)))))))).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">typechecks</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">empty</span> &#x22A2; <span class="id" type="var">equal</span> &#x2208; (<span class="id" type="var">Arrow</span> <span class="id" type="var">Nat</span> (<span class="id" type="var">Arrow</span> <span class="id" type="var">Nat</span> <span class="id" type="var">Nat</span>)).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">equal</span>. <span class="id" type="tactic">auto</span> 10. <span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
<span class="comment">(*&nbsp;GRADE_THEOREM&nbsp;0.25:&nbsp;typechecks&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">reduces</span> :<br/>
&nbsp;&nbsp;(<span class="id" type="var">app</span> (<span class="id" type="var">app</span> <span class="id" type="var">equal</span> (<span class="id" type="var">const</span> 4)) (<span class="id" type="var">const</span> 4)) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>&gt;</span><span style='vertical-align:15%;'>*</span></span></span> (<span class="id" type="var">const</span> 1).<br/>
<span class="id" type="keyword">Proof</span>.<br/>
<span class="comment">(*&nbsp;<br/>
&nbsp;&nbsp;unfold&nbsp;equal.&nbsp;normalize.<br/>
*)</span><br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
<span class="comment">(*&nbsp;GRADE_THEOREM&nbsp;0.25:&nbsp;reduces&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">reduces2</span> :<br/>
&nbsp;&nbsp;(<span class="id" type="var">app</span> (<span class="id" type="var">app</span> <span class="id" type="var">equal</span> (<span class="id" type="var">const</span> 4)) (<span class="id" type="var">const</span> 5)) <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>&gt;</span><span style='vertical-align:15%;'>*</span></span></span> (<span class="id" type="var">const</span> 0).<br/>
<span class="id" type="keyword">Proof</span>.<br/>
<span class="comment">(*&nbsp;<br/>
&nbsp;&nbsp;unfold&nbsp;equal.&nbsp;normalize.<br/>
*)</span><br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">End</span> <span class="id" type="var">FixTest3</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Module</span> <span class="id" type="var">FixTest4</span>.<br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;let&nbsp;evenodd&nbsp;=<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fix<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(\eo:&nbsp;(Nat<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>Nat&nbsp;*&nbsp;Nat<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>Nat).<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;e&nbsp;=&nbsp;\n:Nat.&nbsp;test0&nbsp;n&nbsp;then&nbsp;1&nbsp;else&nbsp;eo.snd&nbsp;(pred&nbsp;n)&nbsp;in<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;o&nbsp;=&nbsp;\n:Nat.&nbsp;test0&nbsp;n&nbsp;then&nbsp;0&nbsp;else&nbsp;eo.fst&nbsp;(pred&nbsp;n)&nbsp;in<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(e,o))&nbsp;in<br/>
&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;even&nbsp;=&nbsp;evenodd.fst&nbsp;in<br/>
&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;odd&nbsp;&nbsp;=&nbsp;evenodd.snd&nbsp;in<br/>
&nbsp;&nbsp;&nbsp;&nbsp;(even&nbsp;3,&nbsp;even&nbsp;4)<br/>
*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">eotest</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="var">tlet</span> <span class="id" type="var">evenodd</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">tfix</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">abs</span> <span class="id" type="var">eo</span> (<span class="id" type="var">Prod</span> (<span class="id" type="var">Arrow</span> <span class="id" type="var">Nat</span> <span class="id" type="var">Nat</span>) (<span class="id" type="var">Arrow</span> <span class="id" type="var">Nat</span> <span class="id" type="var">Nat</span>))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">pair</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">abs</span> <span class="id" type="var">n</span> <span class="id" type="var">Nat</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">test0</span> (<span class="id" type="var">var</span> <span class="id" type="var">n</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">const</span> 1)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">app</span> (<span class="id" type="var">snd</span> (<span class="id" type="var">var</span> <span class="id" type="var">eo</span>)) (<span class="id" type="var">prd</span> (<span class="id" type="var">var</span> <span class="id" type="var">n</span>)))))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">abs</span> <span class="id" type="var">n</span> <span class="id" type="var">Nat</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">test0</span> (<span class="id" type="var">var</span> <span class="id" type="var">n</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">const</span> 0)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">app</span> (<span class="id" type="var">fst</span> (<span class="id" type="var">var</span> <span class="id" type="var">eo</span>)) (<span class="id" type="var">prd</span> (<span class="id" type="var">var</span> <span class="id" type="var">n</span>))))))))<br/>
&nbsp;&nbsp;(<span class="id" type="var">tlet</span> <span class="id" type="var">even</span> (<span class="id" type="var">fst</span> (<span class="id" type="var">var</span> <span class="id" type="var">evenodd</span>))<br/>
&nbsp;&nbsp;(<span class="id" type="var">tlet</span> <span class="id" type="var">odd</span> (<span class="id" type="var">snd</span> (<span class="id" type="var">var</span> <span class="id" type="var">evenodd</span>))<br/>
&nbsp;&nbsp;(<span class="id" type="var">pair</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">app</span> (<span class="id" type="var">var</span> <span class="id" type="var">even</span>) (<span class="id" type="var">const</span> 3))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">app</span> (<span class="id" type="var">var</span> <span class="id" type="var">even</span>) (<span class="id" type="var">const</span> 4))))).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">typechecks</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">empty</span> &#x22A2; <span class="id" type="var">eotest</span> &#x2208; (<span class="id" type="var">Prod</span> <span class="id" type="var">Nat</span> <span class="id" type="var">Nat</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">eotest</span>. <span class="id" type="tactic">eauto</span> 30. <span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
<span class="comment">(*&nbsp;GRADE_THEOREM&nbsp;0.25:&nbsp;typechecks&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">reduces</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">eotest</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>&gt;</span><span style='vertical-align:15%;'>*</span></span></span> (<span class="id" type="var">pair</span> (<span class="id" type="var">const</span> 0) (<span class="id" type="var">const</span> 1)).<br/>
<span class="id" type="keyword">Proof</span>.<br/>
<span class="comment">(*&nbsp;<br/>
&nbsp;&nbsp;unfold&nbsp;eotest.&nbsp;normalize.<br/>
*)</span><br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
<span class="comment">(*&nbsp;GRADE_THEOREM&nbsp;0.25:&nbsp;reduces&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">End</span> <span class="id" type="var">FixTest4</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">End</span> <span class="id" type="var">Examples</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 

<div class="doc">
<a name="lab274"></a><h2 class="section">定型的性质</h2>

<div class="paragraph"> </div>

 对扩展后的系统证明其可归约性与保型性类似于 STLC，但证明会更长。
</div>

<div class="doc">
<a name="lab275"></a><h3 class="section">可归约性</h3>

<div class="paragraph"> </div>

<a name="lab276"></a><h4 class="section">练习：3 星, standard (STLCE_progress)</h4>
 Complete the proof of <span class="inlinecode"><span class="id" type="tactic">progress</span></span>.

<div class="paragraph"> </div>

    Theorem: Suppose empty &#x22A2; t &#x2208; T.  Then either
      1. t is a value, or
      2. t &mdash;&gt; t' for some t'.

<div class="paragraph"> </div>

    Proof: By induction on the given typing derivation. 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="tactic">progress</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">t</span> <span class="id" type="var">T</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">empty</span> &#x22A2; <span class="id" type="var">t</span> &#x2208; <span class="id" type="var">T</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">value</span> <span class="id" type="var">t</span> ∨ <span style='font-size:120%;'>&exist;</span><span class="id" type="var">t'</span>, <span class="id" type="var">t</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t'</span>.<br/>
<div class="togglescript" id="proofcontrol1" onclick="toggleDisplay('proof1');toggleDisplay('proofcontrol1')"><span class="show"></span></div>
<div class="proofscript" id="proof1" onclick="toggleDisplay('proof1');toggleDisplay('proofcontrol1')">
<span class="id" type="keyword">Proof</span> <span class="id" type="keyword">with</span> <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">t</span> <span class="id" type="var">T</span> <span class="id" type="var">Ht</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">remember</span> <span class="id" type="var">empty</span> <span class="id" type="keyword">as</span> <span class="id" type="var">Gamma</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">generalize</span> <span class="id" type="tactic">dependent</span> <span class="id" type="var">HeqGamma</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">Ht</span>; <span class="id" type="tactic">intros</span> <span class="id" type="var">HeqGamma</span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Var&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;给定的类型导出式中的最后规则不可能是<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">T_Var</span></span>,&nbsp;因为它不可能是&nbsp;<span class="inlinecode"><span class="id" type="var">empty</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode">:</span> <span class="inlinecode"><span class="id" type="var">T</span></span>&nbsp;这种情形（因为上下文为空）.&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Abs&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;如果规则&nbsp;<span class="inlinecode"><span class="id" type="var">T_Abs</span></span>&nbsp;最后被使用，那么<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">t</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">abs</span></span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">T<sub>11</sub></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>12</sub></span></span>，也即一个值。&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">left</span>...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_App&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;如果最后被使用的规则是&nbsp;<span class="inlinecode"><span class="id" type="var">T_App</span></span>，那么&nbsp;<span class="inlinecode"><span class="id" type="var">t</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span>，<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;且有规则的形式我们可以知道<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">empty</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> <span class="inlinecode">:</span> <span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span></span> <span class="inlinecode">→</span> <span class="inlinecode"><span class="id" type="var">T<sub>2</sub></span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">empty</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span> <span class="inlinecode">:</span> <span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;由归纳假设，t<sub>1</sub>&nbsp;和&nbsp;2&nbsp;均要么是值，要么可前进一步。*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">right</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHt1</span>; <span class="id" type="tactic">subst</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>1</sub>&nbsp;是值&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHt2</span>; <span class="id" type="tactic">subst</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;t<sub>2</sub>&nbsp;是值&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;如果&nbsp;<span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span>&nbsp;和&nbsp;<span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span>&nbsp;同时为值，那么我们可得<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">abs</span></span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">T<sub>11</sub></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>12</sub></span></span>，因为抽象是函数类型唯一可能的值。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;但由规则&nbsp;<span class="inlinecode"><span class="id" type="var">ST_AppAbs</span></span>&nbsp;可得<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode">(<span class="id" type="var">abs</span></span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">T<sub>11</sub></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>12</sub></span>)</span> <span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span> <span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode">[<span class="id" type="var">x</span>:=<span class="id" type="var">t<sub>2</sub></span>]<span class="id" type="var">t<sub>12</sub></span></span>。*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>; <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">try</span> <span class="id" type="var">solve_by_invert</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>(<span class="id" type="tactic">subst</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>12</sub></span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;t<sub>2</sub>&nbsp;可前进&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;如果&nbsp;<span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span>&nbsp;是值且&nbsp;<span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span> <span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>2</sub>'</span></span>，<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;那么由&nbsp;<span class="inlinecode"><span class="id" type="var">ST_App2</span></span>&nbsp;可得&nbsp;<span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span> <span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>2</sub>'</span></span>。&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>0</sub></span> <span class="id" type="keyword">as</span> [<span class="id" type="var">t<sub>2</sub>'</span> <span class="id" type="var">Hstp</span>]. <span style='font-size:120%;'>&exist;</span>(<span class="id" type="var">app</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub>'</span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>1</sub>&nbsp;可前进&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;最后，如果&nbsp;<span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> <span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>1</sub>'</span></span>，那么由&nbsp;<span class="inlinecode"><span class="id" type="var">ST_App1</span></span>&nbsp;可得&nbsp;<span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span> <span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>1</sub>'</span></span> <span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span>。*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">Hstp</span>]. <span style='font-size:120%;'>&exist;</span>(<span class="id" type="var">app</span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">t<sub>2</sub></span>)...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Nat&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">left</span>...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Succ&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">right</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHt</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>1</sub>&nbsp;是值&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>; <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">try</span> <span class="id" type="var">solve_by_invert</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>(<span class="id" type="var">const</span> (<span class="id" type="var">S</span> <span class="id" type="var">n<sub>1</sub></span>))...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>1</sub>&nbsp;可前进&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">Hstp</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>(<span class="id" type="var">scc</span> <span class="id" type="var">t<sub>1</sub>'</span>)...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Pred&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">right</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHt</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>1</sub>&nbsp;是值&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>; <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">try</span> <span class="id" type="var">solve_by_invert</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>(<span class="id" type="var">const</span> (<span class="id" type="var">pred</span> <span class="id" type="var">n<sub>1</sub></span>))...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>1</sub>&nbsp;可前进&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">Hstp</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>(<span class="id" type="var">prd</span> <span class="id" type="var">t<sub>1</sub>'</span>)...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Mult&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">right</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHt1</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>1</sub>&nbsp;是值&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHt2</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;t<sub>2</sub>&nbsp;是值&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>; <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">try</span> <span class="id" type="var">solve_by_invert</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>0</sub></span>; <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">try</span> <span class="id" type="var">solve_by_invert</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>(<span class="id" type="var">const</span> (<span class="id" type="var">mult</span> <span class="id" type="var">n<sub>1</sub></span> <span class="id" type="var">n<sub>0</sub></span>))...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;t<sub>2</sub>&nbsp;可前进&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>0</sub></span> <span class="id" type="keyword">as</span> [<span class="id" type="var">t<sub>2</sub>'</span> <span class="id" type="var">Hstp</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>(<span class="id" type="var">mlt</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub>'</span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>1</sub>&nbsp;可前进&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">Hstp</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>(<span class="id" type="var">mlt</span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">t<sub>2</sub></span>)...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Test0&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">right</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHt1</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>1</sub>&nbsp;是值&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>; <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">try</span> <span class="id" type="var">solve_by_invert</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">n<sub>1</sub></span> <span class="id" type="keyword">as</span> [|<span class="id" type="var">n<sub>1</sub>'</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;n<sub>1</sub>=0&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span><span class="id" type="var">t<sub>2</sub></span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;n<sub>1</sub>&lt;&gt;0&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span><span class="id" type="var">t<sub>3</sub></span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>1</sub>&nbsp;可前进&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">H<sub>0</sub></span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>(<span class="id" type="var">test0</span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>)...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Inl&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHt</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>1</sub>&nbsp;可前进&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">right</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">Hstp</span>]...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;存在&nbsp;(tinl&nbsp;_&nbsp;t<sub>1</sub>')...&nbsp;*)</span><br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Inr&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHt</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>1</sub>&nbsp;可前进&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">right</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">Hstp</span>]...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;存在&nbsp;(tinr&nbsp;_&nbsp;t<sub>1</sub>')...&nbsp;*)</span><br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Case&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">right</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHt1</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>0</sub>&nbsp;是值&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>; <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">try</span> <span class="id" type="var">solve_by_invert</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;t<sub>0</sub>&nbsp;是&nbsp;inl&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>([<span class="id" type="var">x<sub>1</sub></span>:=<span class="id" type="var">v</span>]<span class="id" type="var">t<sub>1</sub></span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;t<sub>0</sub>&nbsp;是&nbsp;inr&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>([<span class="id" type="var">x<sub>2</sub></span>:=<span class="id" type="var">v</span>]<span class="id" type="var">t<sub>2</sub></span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>0</sub>&nbsp;可前进&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">t<sub>0</sub>'</span> <span class="id" type="var">Hstp</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>(<span class="id" type="var">tcase</span> <span class="id" type="var">t<sub>0</sub>'</span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span>)...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Nil&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">left</span>...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Cons&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHt1</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;头部（head）是值&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHt2</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;尾部（tail）可前进&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">right</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>0</sub></span> <span class="id" type="keyword">as</span> [<span class="id" type="var">t<sub>2</sub>'</span> <span class="id" type="var">Hstp</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>(<span class="id" type="var">tcons</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub>'</span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;头部可前进&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">right</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">Hstp</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>(<span class="id" type="var">tcons</span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">t<sub>2</sub></span>)...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Lcase&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">right</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHt1</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>1</sub>&nbsp;是值&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>; <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">try</span> <span class="id" type="var">solve_by_invert</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;t<sub>1</sub>=tnil&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span><span class="id" type="var">t<sub>2</sub></span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;t<sub>1</sub>=tcons&nbsp;v<sub>1</sub>&nbsp;vl&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>([<span class="id" type="var">x<sub>2</sub></span>:=<span class="id" type="var">vl</span>]([<span class="id" type="var">x<sub>1</sub></span>:=<span class="id" type="var">v<sub>1</sub></span>]<span class="id" type="var">t<sub>3</sub></span>))...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;t<sub>1</sub>&nbsp;可前进&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">Hstp</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>(<span class="id" type="var">tlcase</span> <span class="id" type="var">t<sub>1</sub>'</span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>)...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Unit&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">left</span>...<br/><hr class='doublespaceincode'/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;Complete&nbsp;the&nbsp;proof.&nbsp;*)</span><br/><hr class='doublespaceincode'/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;pairs&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;let&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;fix&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
</div>

<br/>
<span class="comment">(*&nbsp;请勿修改下面这一行：&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">manual_grade_for_progress</span> : <span class="id" type="var">option</span> (<span class="id" type="var">nat</span>*<span class="id" type="var">string</span>) := <span class="id" type="var">None</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 

<div class="doc">
<a name="lab277"></a><h3 class="section">上下文不变性</h3>

<div class="paragraph"> </div>

<a name="lab278"></a><h4 class="section">练习：3 星, standard (STLCE_context_invariance)</h4>
 Complete the definition of <span class="inlinecode"><span class="id" type="var">appears_free_in</span></span>, and the proofs of
   <span class="inlinecode"><span class="id" type="var">context_invariance</span></span> and <span class="inlinecode"><span class="id" type="var">free_in_context</span></span>. 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Inductive</span> <span class="id" type="var">appears_free_in</span> : <span class="id" type="var">string</span> → <span class="id" type="var">tm</span> → <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_var</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">var</span> <span class="id" type="var">x</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_app1</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> → <span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">app</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_app2</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>2</sub></span> → <span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">app</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_abs</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">y</span> <span class="id" type="var">T<sub>11</sub></span> <span class="id" type="var">t<sub>12</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">y</span> ≠ <span class="id" type="var">x</span>  →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>12</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">abs</span> <span class="id" type="var">y</span> <span class="id" type="var">T<sub>11</sub></span> <span class="id" type="var">t<sub>12</sub></span>)<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;数值&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_succ</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">scc</span> <span class="id" type="var">t</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_pred</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">prd</span> <span class="id" type="var">t</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_mult1</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">mlt</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_mult2</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>2</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">mlt</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_test01</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">test0</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_test02</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>2</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">test0</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_test03</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>3</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">test0</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>)<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;sums&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_inl</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t</span> <span class="id" type="var">T</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">tinl</span> <span class="id" type="var">T</span> <span class="id" type="var">t</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_inr</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t</span> <span class="id" type="var">T</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">tinr</span> <span class="id" type="var">T</span> <span class="id" type="var">t</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_case0</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t<sub>0</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>0</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">tcase</span> <span class="id" type="var">t<sub>0</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_case1</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t<sub>0</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">x<sub>1</sub></span> ≠ <span class="id" type="var">x</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">tcase</span> <span class="id" type="var">t<sub>0</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_case2</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t<sub>0</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">x<sub>2</sub></span> ≠ <span class="id" type="var">x</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>2</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">tcase</span> <span class="id" type="var">t<sub>0</sub></span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;列表&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_cons1</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">tcons</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_cons2</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>2</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">tcons</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_lcase1</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">y<sub>1</sub></span> <span class="id" type="var">y<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">tlcase</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">y<sub>1</sub></span> <span class="id" type="var">y<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_lcase2</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">y<sub>1</sub></span> <span class="id" type="var">y<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>2</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">tlcase</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">y<sub>1</sub></span> <span class="id" type="var">y<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">afi_lcase3</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">y<sub>1</sub></span> <span class="id" type="var">y<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">y<sub>1</sub></span> ≠ <span class="id" type="var">x</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">y<sub>2</sub></span> ≠ <span class="id" type="var">x</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t<sub>3</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> (<span class="id" type="var">tlcase</span> <span class="id" type="var">t<sub>1</sub></span> <span class="id" type="var">t<sub>2</sub></span> <span class="id" type="var">y<sub>1</sub></span> <span class="id" type="var">y<sub>2</sub></span> <span class="id" type="var">t<sub>3</sub></span>)<br/>
<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;Add&nbsp;rules&nbsp;for&nbsp;the&nbsp;following&nbsp;extensions.&nbsp;*)</span><br/>
<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;pairs&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;let&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;fix&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Hint</span> <span class="id" type="var">Constructors</span> <span class="id" type="var">appears_free_in</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Lemma</span> <span class="id" type="var">context_invariance</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span> <span class="id" type="var">Gamma'</span> <span class="id" type="var">t</span> <span class="id" type="var">S</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t</span> &#x2208; <span class="id" type="var">S</span>  →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span>, <span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t</span> → <span class="id" type="var">Gamma</span> <span class="id" type="var">x</span> = <span class="id" type="var">Gamma'</span> <span class="id" type="var">x</span>)  →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma'</span> &#x22A2; <span class="id" type="var">t</span> &#x2208; <span class="id" type="var">S</span>.<br/>
<div class="togglescript" id="proofcontrol2" onclick="toggleDisplay('proof2');toggleDisplay('proofcontrol2')"><span class="show"></span></div>
<div class="proofscript" id="proof2" onclick="toggleDisplay('proof2');toggleDisplay('proofcontrol2')">
<span class="comment">(*&nbsp;Increasing&nbsp;the&nbsp;depth&nbsp;of&nbsp;<span class="inlinecode"><span class="id" type="tactic">eauto</span></span>&nbsp;allows&nbsp;some&nbsp;more&nbsp;simple&nbsp;cases&nbsp;to<br/>
&nbsp;&nbsp;&nbsp;be&nbsp;dispatched&nbsp;automatically.&nbsp;*)</span><br/>
<span class="id" type="keyword">Proof</span> <span class="id" type="keyword">with</span> <span class="id" type="tactic">eauto</span> 30.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span>. <span class="id" type="tactic">generalize</span> <span class="id" type="tactic">dependent</span> <span class="id" type="var">Gamma'</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">H</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">Gamma'</span> <span class="id" type="var">Heqv</span>...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Var&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">T_Var</span>... <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">Heqv</span>...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Abs&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">T_Abs</span>... <span class="id" type="tactic">apply</span> <span class="id" type="var">IHhas_type</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">y</span> <span class="id" type="var">Hafi</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">x</span> <span class="id" type="var">y</span>)...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Case&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">T_Case</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="id" type="tactic">apply</span> <span class="id" type="var">IHhas_type2</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">y</span> <span class="id" type="var">Hafi</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">y</span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="id" type="tactic">apply</span> <span class="id" type="var">IHhas_type3</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">y</span> <span class="id" type="var">Hafi</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">y</span>)...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Lcase&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">T_Lcase</span>... <span class="id" type="tactic">apply</span> <span class="id" type="var">IHhas_type3</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">y</span> <span class="id" type="var">Hafi</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">y</span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">y</span>)...<br/><hr class='doublespaceincode'/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;Complete&nbsp;the&nbsp;proof.&nbsp;*)</span><br/><hr class='doublespaceincode'/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
</div>

<br/>
<span class="id" type="keyword">Lemma</span> <span class="id" type="var">free_in_context</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">t</span> <span class="id" type="var">T</span> <span class="id" type="var">Gamma</span>,<br/>
&nbsp;&nbsp;&nbsp;<span class="id" type="var">appears_free_in</span> <span class="id" type="var">x</span> <span class="id" type="var">t</span> →<br/>
&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; <span class="id" type="var">t</span> &#x2208; <span class="id" type="var">T</span> →<br/>
&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span><span class="id" type="var">T'</span>, <span class="id" type="var">Gamma</span> <span class="id" type="var">x</span> = <span class="id" type="var">Some</span> <span class="id" type="var">T'</span>.<br/>
<div class="togglescript" id="proofcontrol3" onclick="toggleDisplay('proof3');toggleDisplay('proofcontrol3')"><span class="show"></span></div>
<div class="proofscript" id="proof3" onclick="toggleDisplay('proof3');toggleDisplay('proofcontrol3')">
<span class="id" type="keyword">Proof</span> <span class="id" type="keyword">with</span> <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">x</span> <span class="id" type="var">t</span> <span class="id" type="var">T</span> <span class="id" type="var">Gamma</span> <span class="id" type="var">Hafi</span> <span class="id" type="var">Htyp</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">Htyp</span>; <span class="id" type="tactic">inversion</span> <span class="id" type="var">Hafi</span>; <span class="id" type="tactic">subst</span>...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Abs&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHtyp</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">T'</span> <span class="id" type="var">Hctx</span>]... <span style='font-size:120%;'>&exist;</span><span class="id" type="var">T'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hctx</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hctx</span>...<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;T_Case&nbsp;*)</span><br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;left&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHtyp2</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">T'</span> <span class="id" type="var">Hctx</span>]... <span style='font-size:120%;'>&exist;</span><span class="id" type="var">T'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hctx</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hctx</span>...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;right&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHtyp3</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">T'</span> <span class="id" type="var">Hctx</span>]... <span style='font-size:120%;'>&exist;</span><span class="id" type="var">T'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hctx</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hctx</span>...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Lcase&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">clear</span> <span class="id" type="var">Htyp1</span> <span class="id" type="var">IHHtyp1</span> <span class="id" type="var">Htyp2</span> <span class="id" type="var">IHHtyp2</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">IHHtyp3</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">T'</span> <span class="id" type="var">Hctx</span>]... <span style='font-size:120%;'>&exist;</span><span class="id" type="var">T'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hctx</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hctx</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hctx</span>...<br/><hr class='doublespaceincode'/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;Complete&nbsp;the&nbsp;proof.&nbsp;*)</span><br/><hr class='doublespaceincode'/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
</div>

<br/>
<span class="comment">(*&nbsp;请勿修改下面这一行：&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">manual_grade_for_context_invariance</span> : <span class="id" type="var">option</span> (<span class="id" type="var">nat</span>*<span class="id" type="var">string</span>) := <span class="id" type="var">None</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 

<div class="doc">
<a name="lab279"></a><h3 class="section">替换</h3>

<div class="paragraph"> </div>

<a name="lab280"></a><h4 class="section">练习：2 星, standard (STLCE_subst_preserves_typing)</h4>
 Complete the proof of <span class="inlinecode"><span class="id" type="var">substitution_preserves_typing</span></span>. 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Lemma</span> <span class="id" type="var">substitution_preserves_typing</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Gamma</span> <span class="id" type="var">x</span> <span class="id" type="var">U</span> <span class="id" type="var">v</span> <span class="id" type="var">t</span> <span class="id" type="var">S</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">update</span> <span class="id" type="var">Gamma</span> <span class="id" type="var">x</span> <span class="id" type="var">U</span>) &#x22A2; <span class="id" type="var">t</span> &#x2208; <span class="id" type="var">S</span>  →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">empty</span> &#x22A2; <span class="id" type="var">v</span> &#x2208; <span class="id" type="var">U</span>   →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Gamma</span> &#x22A2; ([<span class="id" type="var">x</span>:=<span class="id" type="var">v</span>]<span class="id" type="var">t</span>) &#x2208; <span class="id" type="var">S</span>.<br/>
<div class="togglescript" id="proofcontrol4" onclick="toggleDisplay('proof4');toggleDisplay('proofcontrol4')"><span class="show"></span></div>
<div class="proofscript" id="proof4" onclick="toggleDisplay('proof4');toggleDisplay('proofcontrol4')">
<span class="id" type="keyword">Proof</span> <span class="id" type="keyword">with</span> <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;定理：如果&nbsp;<span class="inlinecode">(<span class="id" type="var">x</span><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span><span class="id" type="var">U</span></span> <span class="inlinecode">;</span> <span class="inlinecode"><span class="id" type="var">Gamma</span>)</span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">t</span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">S</span></span>&nbsp;且&nbsp;<span class="inlinecode"><span class="id" type="var">empty</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">v</span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">U</span></span>，那么<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">Gamma</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode">[<span class="id" type="var">x</span>:=<span class="id" type="var">v</span>]<span class="id" type="var">t</span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">S</span></span>.&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">Gamma</span> <span class="id" type="var">x</span> <span class="id" type="var">U</span> <span class="id" type="var">v</span> <span class="id" type="var">t</span> <span class="id" type="var">S</span> <span class="id" type="var">Htypt</span> <span class="id" type="var">Htypv</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">generalize</span> <span class="id" type="tactic">dependent</span> <span class="id" type="var">Gamma</span>. <span class="id" type="tactic">generalize</span> <span class="id" type="tactic">dependent</span> <span class="id" type="var">S</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;证明：对项&nbsp;<span class="inlinecode"><span class="id" type="var">t</span></span>&nbsp;进行归纳。除了&nbsp;<span class="inlinecode"><span class="id" type="var">var</span></span>&nbsp;和&nbsp;<span class="inlinecode"><span class="id" type="var">abs</span></span>&nbsp;外，多数情形可直接从&nbsp;IH&nbsp;得证。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;他们不是自动完成的，因为我们需要推理变量之间如何交互。*)</span><br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">t</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">S</span> <span class="id" type="var">Gamma</span> <span class="id" type="var">Htypt</span>; <span class="id" type="tactic">simpl</span>; <span class="id" type="tactic">inversion</span> <span class="id" type="var">Htypt</span>; <span class="id" type="tactic">subst</span>...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;var&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">simpl</span>. <span class="id" type="tactic">rename</span> <span class="id" type="var">s</span> <span class="id" type="var">into</span> <span class="id" type="var">y</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;如果&nbsp;<span class="inlinecode"><span class="id" type="var">t</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">y</span></span>，那么通过反演&nbsp;<span class="inlinecode"><span class="id" type="var">update</span></span> <span class="inlinecode"><span class="id" type="var">Gamma</span></span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">U</span></span> <span class="inlinecode"><span class="id" type="var">y</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">Some</span></span> <span class="inlinecode"><span class="id" type="var">S</span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们知道<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">empty</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">v</span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">U</span></span>&nbsp;且<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode">(<span class="id" type="var">x</span><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span><span class="id" type="var">U</span>;<span class="id" type="var">Gamma</span>)</span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">y</span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">S</span></span>。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们想要证明&nbsp;<span class="inlinecode"><span class="id" type="var">Gamma</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode">[<span class="id" type="var">x</span>:=<span class="id" type="var">v</span>]<span class="id" type="var">y</span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">S</span></span>。<br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;有两个情形需要考虑：&nbsp;<span class="inlinecode"><span class="id" type="var">x</span>=<span class="id" type="var">y</span></span>&nbsp;或&nbsp;<span class="inlinecode"><span class="id" type="var">x</span>≠<span class="id" type="var">y</span></span>。&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>1</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">x</span> <span class="id" type="var">y</span>).<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;x=y&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;如果&nbsp;<span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">y</span></span>，那么我们知道&nbsp;<span class="inlinecode"><span class="id" type="var">U</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">S</span></span>，并且<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode">[<span class="id" type="var">x</span>:=<span class="id" type="var">v</span>]<span class="id" type="var">y</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">v</span></span>。因此我们必须证明如果<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">empty</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">v</span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">U</span></span>&nbsp;那么&nbsp;<span class="inlinecode"><span class="id" type="var">Gamma</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">v</span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">U</span></span>。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们已经证明了一个更一般的定理，叫做上下文不变性（context&nbsp;invariance）。*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>1</sub></span>; <span class="id" type="tactic">subst</span>. <span class="id" type="tactic">clear</span> <span class="id" type="var">H<sub>1</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">context_invariance</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">x</span> <span class="id" type="var">Hcontra</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">free_in_context</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span> <span class="id" type="var">S</span> <span class="id" type="var">empty</span> <span class="id" type="var">Hcontra</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">as</span> [<span class="id" type="var">T'</span> <span class="id" type="var">HT'</span>]...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">HT'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;x&lt;&gt;y&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;如果&nbsp;<span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode">≠</span> <span class="inlinecode"><span class="id" type="var">y</span></span>，那么&nbsp;<span class="inlinecode"><span class="id" type="var">Gamma</span></span> <span class="inlinecode"><span class="id" type="var">y</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">Some</span></span> <span class="inlinecode"><span class="id" type="var">S</span></span>&nbsp;并且替换不会产生任何影响。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们可以通过&nbsp;<span class="inlinecode"><span class="id" type="var">T_Var</span></span>&nbsp;证明&nbsp;<span class="inlinecode"><span class="id" type="var">Gamma</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">y</span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">S</span></span>。&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">T_Var</span>...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;abs&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rename</span> <span class="id" type="var">s</span> <span class="id" type="var">into</span> <span class="id" type="var">y</span>. <span class="id" type="tactic">rename</span> <span class="id" type="var">t</span> <span class="id" type="var">into</span> <span class="id" type="var">T<sub>11</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;如果&nbsp;<span class="inlinecode"><span class="id" type="var">t</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">abs</span></span> <span class="inlinecode"><span class="id" type="var">y</span></span> <span class="inlinecode"><span class="id" type="var">T<sub>11</sub></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>0</sub></span></span>，那么我们知道<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode">(<span class="id" type="var">x</span><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span><span class="id" type="var">U</span>;<span class="id" type="var">Gamma</span>)</span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">abs</span></span> <span class="inlinecode"><span class="id" type="var">y</span></span> <span class="inlinecode"><span class="id" type="var">T<sub>11</sub></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>0</sub></span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">T<sub>11</sub></span>→<span class="id" type="var">T<sub>12</sub></span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode">(<span class="id" type="var">y</span><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span><span class="id" type="var">T<sub>11</sub></span>;<span class="id" type="var">x</span><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span><span class="id" type="var">U</span>;<span class="id" type="var">Gamma</span>)</span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">t<sub>0</sub></span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">T<sub>12</sub></span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">empty</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">v</span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">U</span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;根据归纳假设（IH），我们知道对所有的&nbsp;<span class="inlinecode"><span class="id" type="var">S</span></span>&nbsp;和&nbsp;<span class="inlinecode"><span class="id" type="var">Gamma</span></span>，<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;若&nbsp;<span class="inlinecode">(<span class="id" type="var">x</span><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span><span class="id" type="var">U</span>;<span class="id" type="var">Gamma</span>)</span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">t<sub>0</sub></span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">S</span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;则&nbsp;<span class="inlinecode"><span class="id" type="var">Gamma</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode">[<span class="id" type="var">x</span>:=<span class="id" type="var">v</span>]<span class="id" type="var">t<sub>0</sub></span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">S</span></span>。<br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们可以计算<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode">[<span class="id" type="var">x</span>:=<span class="id" type="var">v</span>]<span class="id" type="var">t</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">abs</span></span> <span class="inlinecode"><span class="id" type="var">y</span></span> <span class="inlinecode"><span class="id" type="var">T<sub>11</sub></span></span> <span class="inlinecode">(<span class="id" type="keyword">if</span></span> <span class="inlinecode"><span class="id" type="var">eqb_string</span></span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">y</span></span> <span class="inlinecode"><span class="id" type="keyword">then</span></span> <span class="inlinecode"><span class="id" type="var">t<sub>0</sub></span></span> <span class="inlinecode"><span class="id" type="keyword">else</span></span> <span class="inlinecode">[<span class="id" type="var">x</span>:=<span class="id" type="var">v</span>]<span class="id" type="var">t<sub>0</sub></span>)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;且我们必须证明&nbsp;<span class="inlinecode"><span class="id" type="var">Gamma</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode">[<span class="id" type="var">x</span>:=<span class="id" type="var">v</span>]<span class="id" type="var">t</span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">T<sub>11</sub></span>→<span class="id" type="var">T<sub>12</sub></span></span>.&nbsp;&nbsp;We&nbsp;know<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们知道可以通过&nbsp;<span class="inlinecode"><span class="id" type="var">T_Abs</span></span>&nbsp;来达到此目的，因此剩下的便是证明：<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode">(<span class="id" type="var">y</span><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span><span class="id" type="var">T<sub>11</sub></span>;<span class="id" type="var">Gamma</span>)</span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="keyword">if</span></span> <span class="inlinecode"><span class="id" type="var">eqb_string</span></span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">y</span></span> <span class="inlinecode"><span class="id" type="keyword">then</span></span> <span class="inlinecode"><span class="id" type="var">t<sub>0</sub></span></span> <span class="inlinecode"><span class="id" type="keyword">else</span></span> <span class="inlinecode">[<span class="id" type="var">x</span>:=<span class="id" type="var">v</span>]<span class="id" type="var">t<sub>0</sub></span></span>
                          <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">T<sub>12</sub></span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们考虑两个情形：&nbsp;<span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">y</span></span>&nbsp;and&nbsp;<span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode">≠</span> <span class="inlinecode"><span class="id" type="var">y</span></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">T_Abs</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">x</span> <span class="id" type="var">y</span>) <span class="id" type="keyword">as</span> [<span class="id" type="var">Hxy</span>|<span class="id" type="var">Hxy</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;x=y&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;如果&nbsp;<span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">y</span></span>，那么替换不会产生任何影响。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;上下文不变性展示了&nbsp;<span class="inlinecode"><span class="id" type="var">y</span>:<span class="id" type="var">T<sub>11</sub></span>;<span class="id" type="var">y</span><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span><span class="id" type="var">U</span>;<span class="id" type="var">Gamma</span></span>&nbsp;和&nbsp;<span class="inlinecode"><span class="id" type="var">y</span><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span><span class="id" type="var">T<sub>11</sub></span>;<span class="id" type="var">Gamma</span></span>&nbsp;是等价的。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因为前一个上下文展示了&nbsp;<span class="inlinecode"><span class="id" type="var">t<sub>0</sub></span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">T<sub>12</sub></span></span>，后者也同样。&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">context_invariance</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">x</span> <span class="id" type="var">Hafi</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_string</span> <span class="id" type="var">y</span> <span class="id" type="var">x</span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;x&lt;&gt;y&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;如果&nbsp;<span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode">≠</span> <span class="inlinecode"><span class="id" type="var">y</span></span>，那么归纳假设和上下文不变性允许我们证明<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode">(<span class="id" type="var">y</span><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span><span class="id" type="var">T<sub>11</sub></span>;<span class="id" type="var">x</span><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span><span class="id" type="var">U</span>;<span class="id" type="var">Gamma</span>)</span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">t<sub>0</sub></span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">T<sub>12</sub></span></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode">(<span class="id" type="var">x</span><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span><span class="id" type="var">U</span>;<span class="id" type="var">y</span><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span><span class="id" type="var">T<sub>11</sub></span>;<span class="id" type="var">Gamma</span>)</span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">t<sub>0</sub></span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">T<sub>12</sub></span></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode">(<span class="id" type="var">y</span><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span><span class="id" type="var">T<sub>11</sub></span>;<span class="id" type="var">Gamma</span>)</span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode">[<span class="id" type="var">x</span>:=<span class="id" type="var">v</span>]<span class="id" type="var">t<sub>0</sub></span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">T<sub>12</sub></span></span>&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">IHt</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">context_invariance</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">z</span> <span class="id" type="var">Hafi</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">y</span> <span class="id" type="var">z</span>) <span class="id" type="keyword">as</span> [<span class="id" type="var">Hyz</span>|<span class="id" type="var">Hyz</span>]...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span>...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;tcase&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rename</span> <span class="id" type="var">s</span> <span class="id" type="var">into</span> <span class="id" type="var">x<sub>1</sub></span>. <span class="id" type="tactic">rename</span> <span class="id" type="var">s<sub>0</sub></span> <span class="id" type="var">into</span> <span class="id" type="var">x<sub>2</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">T_Case</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;左侧&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">x</span> <span class="id" type="var">x<sub>1</sub></span>) <span class="id" type="keyword">as</span> [<span class="id" type="var">Hxx1</span>|<span class="id" type="var">Hxx1</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;x&nbsp;=&nbsp;x<sub>1</sub>&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">context_invariance</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">z</span> <span class="id" type="var">Hafi</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_string</span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">z</span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;x&nbsp;&lt;&gt;&nbsp;x<sub>1</sub>&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">IHt2</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">context_invariance</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">z</span> <span class="id" type="var">Hafi</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">x<sub>1</sub></span> <span class="id" type="var">z</span>) <span class="id" type="keyword">as</span> [<span class="id" type="var">Hx1z</span>|<span class="id" type="var">Hx1z</span>]...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">subst</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;右侧&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">x</span> <span class="id" type="var">x<sub>2</sub></span>) <span class="id" type="keyword">as</span> [<span class="id" type="var">Hxx2</span>|<span class="id" type="var">Hxx2</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;x&nbsp;=&nbsp;x<sub>2</sub>&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">context_invariance</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">z</span> <span class="id" type="var">Hafi</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_string</span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">z</span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;x&nbsp;&lt;&gt;&nbsp;x<sub>2</sub>&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">IHt3</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">context_invariance</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">z</span> <span class="id" type="var">Hafi</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">x<sub>2</sub></span> <span class="id" type="var">z</span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">subst</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span>...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;tlcase&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rename</span> <span class="id" type="var">s</span> <span class="id" type="var">into</span> <span class="id" type="var">y<sub>1</sub></span>. <span class="id" type="tactic">rename</span> <span class="id" type="var">s<sub>0</sub></span> <span class="id" type="var">into</span> <span class="id" type="var">y<sub>2</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">T_Lcase</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">x</span> <span class="id" type="var">y<sub>1</sub></span>).<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;x=y<sub>1</sub>&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">simpl</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">context_invariance</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">z</span> <span class="id" type="var">Hafi</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">y<sub>1</sub></span> <span class="id" type="var">z</span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;x&lt;&gt;y<sub>1</sub>&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">x</span> <span class="id" type="var">y<sub>2</sub></span>).<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;x=y<sub>2</sub>&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">context_invariance</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">z</span> <span class="id" type="var">Hafi</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">y<sub>2</sub></span> <span class="id" type="var">z</span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;x&lt;&gt;y<sub>2</sub>&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">IHt3</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">context_invariance</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">z</span> <span class="id" type="var">Hafi</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">update</span>, <span class="id" type="var">t_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">y<sub>1</sub></span> <span class="id" type="var">z</span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">subst</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">y<sub>2</sub></span> <span class="id" type="var">z</span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">subst</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span>...<br/><hr class='doublespaceincode'/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;Complete&nbsp;the&nbsp;proof.&nbsp;*)</span><br/><hr class='doublespaceincode'/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
</div>

<br/>
<span class="comment">(*&nbsp;请勿修改下面这一行：&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">manual_grade_for_substitution_preserves_typing</span> : <span class="id" type="var">option</span> (<span class="id" type="var">nat</span>*<span class="id" type="var">string</span>) := <span class="id" type="var">None</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 

<div class="doc">
<a name="lab281"></a><h3 class="section">保型性</h3>

<div class="paragraph"> </div>

<a name="lab282"></a><h4 class="section">练习：3 星, standard (STLCE_preservation)</h4>
 Complete the proof of <span class="inlinecode"><span class="id" type="var">preservation</span></span>. 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">preservation</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">t</span> <span class="id" type="var">t'</span> <span class="id" type="var">T</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">empty</span> &#x22A2; <span class="id" type="var">t</span> &#x2208; <span class="id" type="var">T</span>  →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">t</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">t'</span>  →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">empty</span> &#x22A2; <span class="id" type="var">t'</span> &#x2208; <span class="id" type="var">T</span>.<br/>
<div class="togglescript" id="proofcontrol5" onclick="toggleDisplay('proof5');toggleDisplay('proofcontrol5')"><span class="show"></span></div>
<div class="proofscript" id="proof5" onclick="toggleDisplay('proof5');toggleDisplay('proofcontrol5')">
<span class="id" type="keyword">Proof</span> <span class="id" type="keyword">with</span> <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">t</span> <span class="id" type="var">t'</span> <span class="id" type="var">T</span> <span class="id" type="var">HT</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;定理：如果&nbsp;<span class="inlinecode"><span class="id" type="var">empty</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">t</span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">T</span></span>&nbsp;且&nbsp;<span class="inlinecode"><span class="id" type="var">t</span></span> <span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">t'</span></span>，那么<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">empty</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">t'</span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">T</span></span>.&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="id" type="var">remember</span> <span class="id" type="var">empty</span> <span class="id" type="keyword">as</span> <span class="id" type="var">Gamma</span>. <span class="id" type="tactic">generalize</span> <span class="id" type="tactic">dependent</span> <span class="id" type="var">HeqGamma</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">generalize</span> <span class="id" type="tactic">dependent</span> <span class="id" type="var">t'</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;证明：对给定的类型导出式进行归纳。许多情形是矛盾的（<span class="inlinecode"><span class="id" type="var">T_Var</span></span>,&nbsp;<span class="inlinecode"><span class="id" type="var">T_Abs</span></span>），<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们只证明有趣的那几个情形。*)</span><br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">HT</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">t'</span> <span class="id" type="var">HeqGamma</span> <span class="id" type="var">HE</span>; <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">inversion</span> <span class="id" type="var">HE</span>; <span class="id" type="tactic">subst</span>...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_App&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;如果最后被使用的规则是&nbsp;<span class="inlinecode"><span class="id" type="var">T_App</span></span>，那么&nbsp;<span class="inlinecode"><span class="id" type="var">t</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span>，<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;且有三个规则会被用于证明&nbsp;<span class="inlinecode"><span class="id" type="var">t</span></span> <span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:6%;'><span style='letter-spacing:-.2em;'>-</span><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span></span> <span class="inlinecode"><span class="id" type="var">t'</span></span>：<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">ST_App1</span></span>，<span class="inlinecode"><span class="id" type="var">ST_App2</span></span>，和&nbsp;<span class="inlinecode"><span class="id" type="var">ST_AppAbs</span></span>。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在前两个情形中，结果可直接从归纳假设中得证。&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">HE</span>; <span class="id" type="tactic">subst</span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;ST_AppAbs&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;对于第三个情形，假设<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">t<sub>1</sub></span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">abs</span></span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">T<sub>11</sub></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>12</sub></span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;且<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">t<sub>2</sub></span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">v<sub>2</sub></span></span>。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们必须证明&nbsp;<span class="inlinecode"><span class="id" type="var">empty</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode">[<span class="id" type="var">x</span>:=<span class="id" type="var">v<sub>2</sub></span>]<span class="id" type="var">t<sub>12</sub></span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">T<sub>2</sub></span></span>。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;由假设，我们可得<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">empty</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">tabs</span></span> <span class="inlinecode"><span class="id" type="var">x</span></span> <span class="inlinecode"><span class="id" type="var">T<sub>11</sub></span></span> <span class="inlinecode"><span class="id" type="var">t<sub>12</sub></span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span>→<span class="id" type="var">T<sub>2</sub></span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;且，由反演可得<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">x</span>:<span class="id" type="var">T<sub>1</sub></span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">t<sub>12</sub></span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">T<sub>2</sub></span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们已经证明了类型在替换下的不变性，且根据假设可得<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="inlinecode"><span class="id" type="var">empty</span></span> <span class="inlinecode">&#x22A2;</span> <span class="inlinecode"><span class="id" type="var">v<sub>2</sub></span></span> <span class="inlinecode">&#x2208;</span> <span class="inlinecode"><span class="id" type="var">T<sub>1</sub></span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;证毕。&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">substitution_preserves_typing</span> <span class="id" type="keyword">with</span> <span class="id" type="var">T<sub>1</sub></span>...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">HT<sub>1</sub></span>...<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;T_Case&nbsp;*)</span><br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;ST_CaseInl&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">HT<sub>1</sub></span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">substitution_preserves_typing</span>...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;ST_CaseInr&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">HT<sub>1</sub></span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">substitution_preserves_typing</span>...<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;T_Lcase&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;ST_LcaseCons&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">HT<sub>1</sub></span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">substitution_preserves_typing</span> <span class="id" type="keyword">with</span> (<span class="id" type="var">List</span> <span class="id" type="var">T<sub>1</sub></span>)...<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">substitution_preserves_typing</span> <span class="id" type="keyword">with</span> <span class="id" type="var">T<sub>1</sub></span>...<br/><hr class='doublespaceincode'/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;Complete&nbsp;the&nbsp;proof.&nbsp;*)</span><br/><hr class='doublespaceincode'/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;fst&nbsp;and&nbsp;snd&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;let&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;fix&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
</div>

<br/>
<span class="comment">(*&nbsp;请勿修改下面这一行：&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">manual_grade_for_preservation</span> : <span class="id" type="var">option</span> (<span class="id" type="var">nat</span>*<span class="id" type="var">string</span>) := <span class="id" type="var">None</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 
<div class="code code-tight">

<span class="id" type="keyword">End</span> <span class="id" type="var">STLCExtended</span>.<br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;Mon&nbsp;Oct&nbsp;28&nbsp;08:15:19&nbsp;UTC&nbsp;2019&nbsp;*)</span><br/>
</div>
</div>



</div>

</body>
</html>